티스토리 뷰

728x90
반응형

객체는 인터페이스를 사용해 참조하라


  • 적합한 인터페이스만 있다면 매개변수뿐 아니라 반환값, 변수, 필드를 전부 인터페이스 타입으로 선언하는게 좋습니다.

 

💡유연한 프로그램 작성

  • LinkedHashSet을 사용하는 인터페이스 타입 변수를 선언하면 유연하게 변경할 수 있습니다.
//좋은 예
Set<Son> sonSet = new LinkedHashSet<>();

//나쁜 예
LinkedHashSet<Son> sonSet = new LinkedHashSet<>();

 

💡다른 타입으로 변경

  • 좋은 예는 Set 인터페이스 타입이기 때문에 다른 구현체로 변경해도 에러가 발생하지 않습니다. 하지만 나쁜 예의 경우 LinkedHashSet 인터페이스 타입이기 때문에 다른 구현체를 받는다면 컴파일 에러가 발생하게 됩니다.
//좋은 예
Set<Son> sonSet = new TreeSet<>();

//나쁜 예
LinkedHashSet<Son> sonSet = new TreeSet<>(); //컴파일 에러 발생!

 

💡변경 시 주의점

  • 아무리 좋은 예시라도 로직에서 LinkedHashSet을 사용하여 순서를 보장받아 사용하는 경우 갑작스레 HashSet으로 변경하면 내부 로직에 문제가 발생할 수 있습니다. 그렇기 때문에 내부 로직을 파악하고 변경할 필요성이 있습니다.

 

💡인터페이스 타입의 장점

  • 인터페이스 타입을 사용하면 유연하게 상황을 대체할 수 있을뿐만 아니라 다른 타입의 객체를 사용하더라도 컴파일/런타임 에러에 대한 걱정을 줄일 수 있습니다.

 

💡인터페이스 타입의 단점

  • 인터페이스에 선언된 메서드를 구현한 메서드만 사용할 수 있습니다.
  • 특정 구현체의 내부 메서드를 못 사용할 수도 있습니다.

 

💡인터페이스가 아닌 클래스 타입을 사용해야 하는 경우

  • 적합한 인터페이스가 없다면 클래스를 사용해야 합니다. String, BigInteger 같은 값 클래스가 그렇습니다. 또한 Integer, Long과 같은 타입을 사용할 때 Number와 같은 상위 타입을 사용하면 괜찮지 않을까? 생각할 수 있지만 그렇게하면 형변환이 발생할 때 특정 테이터가 절삭되어 다른 결과를 초래할 수 있습니다 이러한 경우가 있으니 본래의 클래스로 참조하는것이 좋습니다.
  • PriorityQueue 클래스에는 Queue 인터페이스에 없는 comparator 메서드를 제공하고 있습니다. 이렇게 상위 인터페이스에서 제공하지 않는 메서드를 사용하는 경우에는 클래스 타입을 사용해야 합니다. 하지만 명확하게 특정 메서드를 사용해야 하는 경우가 아니라면 인터페이스를 참조하도록해도 무방합니다.
  • java.io 패키지에서 제공되는 여러 클래스(InputStream, OutputStream)는 클래스 기반이기 때문에 인터페이스가 따로 없습니다. 하지만 이런 경우에도 최대한 구현체보다는 추상 클래스를 참조하는게 좋습니다.

 

✔️ 정리

  • 인터페이스 타입을 사용하여 참조를 하면 상황을 유연하게 대처할 수 있습니다. 만약 적합한 인터페이스가 없다면 클래스 계층구조에서 가장 추상적인(abstract) 타입으로 사용하는게 좋습니다.

 

 

 

 

 

728x90
반응형