적합한 인터페이스만 있다면 매개변수뿐만 아니라 반환 값, 변수, 필드를 전부 인터페이스 타입으로 선언하는 것이 좋다.
객체의 실제 클래스를 사용해야 할 상황은 '오직' 생성자로 생성할 때뿐이다.
인터페이스를 타입으로 사용하는 습관을 길러두면 프로그램이 훨씬 더 유연해질 것이다.
나중에 구현 클래스를 교체하고자 하면 그저 새 클래스의 생성자를 호출해 주기만 하면 된다.
선언 타입과 구현 타입을 동시에 바꿀 수 있으니, 변수를 구현 타입으로 선언해도 괜찮을 거로 생각할 수도 있다.
하지만 자칫하면 프로그램이 컴파일되지 않는다.
예컨대 클라이언트에서 기존 타입에서만 제공하는 메서드를 사용했거나, 기존 타입을 사용해야 하는 다른 메서드에 그 인스턴스를 넘겼다고 해보자.
그러면 새로운 코드에서는 컴파일되지 않을 것이다.
변수를 인터페이스 타입으로 선언하며 이런 일이 발생하지 않는다.
하지만 적합한 인터페이스가 없다면 당연히 클래스로 참조해야 한다.
적합한 인터페이스가 없는 경우는 우선 클래스 기반으로 작성된 프레임워크가 제공하는 객체들이다.
이런 경우라도 특정 구현 클래스보다는 기반 클래스를 사용해 참조하는 것이 좋다.
또 다른 경우는 인터페이스에는 없는 특별한 메서드를 제공하는 클래스들이다.
적합한 인터페이스가 없다면 클래스 계층구조 중 필요한 기능을 만족하는 가장 덜 구체적인 상위 클래스를 타입으로 사용하는 것이 좋다.