제리 devlog

[이펙티브 자바] 객체는 인터페이스를 사용해 참조하라 본문

Java

[이펙티브 자바] 객체는 인터페이스를 사용해 참조하라

제리 . 2020. 11. 23. 15:38

객체는 클래스가 아닌 인터페이스로 참조하라. 이 말이 무슨 뜻일까?

//좋은 예 
Set<String> set = new LinkedHashSet<>();

//나쁜 예
LinkedHashSet<String> set = new LinkedHashSet<>();

객체를 생성할 때 LinkedHashSet으로 객체를 만들지만 업캐스팅을 사용하고있다. 업캐스팅을 사용하게되면 상위 인터페이스에 있는 구현체를 사용할 수 있지만 LinkedHashSet만이 가진 메서드를 사용할 순 없다.

 

 

인터페이스가 갖는 유연성

 

더 나은 성능이나 신기능을 사용하기위해 원래 구현했던 타입을 변경하는 경우가 있다. 

//좋은 예  LinkedHashSet -> HashSet으로 구현체를 변경해도 코드가 변하지 않음
Set<String> set = new HashSet<>();

set.add(...);
set.remove(...);
set.size(...);
set.contains(...);


public void ...(Set<String> set, ...)

public int ...(Set<String> set, ...)

public String ...(Set<String> set, ...)

public boolean ...(Set<String> set, ...)

public long ...(Set<String> set, ...)

구현 타입이 변경되도 유연하게 대처할 수 있는 좋은 예이다. 인터페이스를 참조하여 만든 객체는 구현타입이 변하더라도 인터페이스에 있는 메서드를 그대로 사용할 수 있다.

 

//나쁜 예  LinkedHashSet -> HashSet으로 구현체를 변경하면 관련된 모든 코드를 변경해야함
HashSet<String> set = new HashSet<>();

set.add(...);
set.remove(...);
set.size(...);
set.contains(...);


//컴파일 에러 발생
public void ...(LinkedHashSet<String> set, ...)

public int ...(LinkedHashSet<String> set, ...)

public String ...(LinkedHashSet<String> set, ...)

public boolean ...(LinkedHashSet<String> set, ...)

public long ...(LinkedHashSet<String> set, ...)

반면, 객체 클래스로 만든다면 관련되어있던 모든 코드를 수정해야 컴파일 오류가 발생하지 않는다.

 

적합한 인터페이스가 없다면 당연히 클래스로 참조해야한다.

String과 Integer같은 클래스 값을 표현하는 클래스가 그렇다. 값 클래스를 여러가지로 구현될 수 있다고 생각하고 설계하는 일은 거의 없다. 따라서 final인 경우가 많고 상응하는 인터페이스가 드물다. 

 

적합한 인터페이스가 없는 다른 부류는 클래스 기반으로 작성된 프레임워크가 제공하는 객체들이다. 이런 경우에도 특정 구현 클래스보다는 (보통은 추상 클래스인) 기반 클래스를 사용해 참조하는게 좋다. OutputStream등 자바 io패키지가 여기에 속한다.

OutputStream outputStream = new FileOutputStream("");

 

마지막으로 인터페이스에 없는 기능을 사용할 때 주의해야한다. PriorityQueue의 경우 Queue인터페이스에 없는 comparator 메서드를 제공한다. 클래스 타입을 직접 사용하는 경우는 이런 특정 메소드를 사용해야하는 상황으로 최소하시켜야하며 남발해선 안된다.

 

적한한 인터페이스가 없다면 클래스의 계층구조 중 필요한 기능을 만족하는 가장 덜 구체적인(상위의) 클래스를 타입으로 사용하자.

 

-결론-

객체는 최대한 인터페이스를 활용하여 구현체가 바뀌어도 유연성을 유지하게하자. 단, 적합한 인터페이스가 없다면 가장 덜 구체적인 상위의 클래스를 타입으로하자.

Comments