적합한 인터페이스만 있다면 매개변수뿐 아니라 반환값, 변수, 필드를 전부 인터페이스 타입으로 선언하라.
// 좋은 예
Set<Son> sonSet = new LinkedHashSet<>();
// 나쁜 예
LinkedHashSet<Son> sonSet = new LinkedHashSet<>();
인터페이스를 타입으로 사용하면 프로그램이 훨씬 유연해진다.
나중에 구현 클래스를 교체할 때 새 클래스의 생성자를 호출해주기만 하면 된다.
Set<Son> sonSet = new HashSet<>();
적합한 인터페이스가 없다면 당연히 클래스로 참조해야 한다.
예를 들어 인터페이스에는 없는 특별한 메서드를 제공하는 클래스들이다.
List<Integer> list = new ArrayList<>();
ArrayList<Integer> list2 = new ArrayList<>();
// list.ensureCapacity
list2.ensureCapacity(3);
ensureCapacity()
같은 메서드는 ArrayList
에만 구현되어 있다. 그래서 List
인터페이스로 받으면 사용할 수 없다.