아이템20. 추상 클래스보다는 인터페이스를 우선하라
자바가 제공하는 다중 구현 메커니즘은 인터페이스와 추상 클래스, 이렇게 두 가지다.
추상 클래스 vs 인터페이스
자바 8부터는 인터페이스도 디폴트 메서드를 제공할 수 있게 되어, 두 방식 모두 인스턴스 메서드를 구현 형태로 제공할 수 있다.
둘의 가장 큰 차이는 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 한다는 점이다.
즉, 추상 클래스는 좀 더 상세한 구현과 필드를 가질 수 있지만, 인터페이스와 달리 다중 상속은 불가능 하다는 점이다.
비슷한 역할을 하는듯 하지만, 인터페이스는 추상 클래스에 비해 다양한 장점이 있다.
- 기존 클래스에 손쉽게 새로운 인터페이스를 구현해 넣을 수 있다.
- 인터페이스는 믹스인(mixin) 정의에 안성맞춤이다.
- 혼합이라는 뜻을 가지고 있는 믹스인은 믹스인을 구현할 클래스에 원래의 '주된 타입' 외에 특정 선택적 행위를 제공한다고 선언하는 효과를 줄 수 있다.
- 계층구조 없는 타입 프레임워크를 만들 수 있다.
- 물론 계층이 적절하게 나뉘어지는 개념도 존재하지만, 현실에서는 계층을 엄격하게 구분하기 어려운 개념도 있다. 곧 알아볼 Singer, Songwriter 인터페이스로 알아보자.
public interface Singer {
AudioClip sing(Song s);
}
public interface Songwriter {
Song compose(int chartPosition);
}
현실에는 싱어송라이터도 있다. 즉 작곡도 하는 가수가 꽤 있다. 그래서 해당 개념을 구현하려면 다음처럼 새로운 계층을 만들면 된다.
public interface SingerSongwriter extends Singer, Songwriter {
AudioClip strum();
void actSensitive();
}
위의 세 사례 모두 추상 클래스에서는 구현하기가 어려운 부분이다.
디폴트 메서드
인터페이스의 메서드 중 구현 방법이 명백한 것이 있다면, 그 구현을 디폴트 메서드로 제공해 프로그래머들의 부담을 덜어줄 수 있다.
디폴트 메서드를 제공할 때 상속하려는 사람을 위해 @implSpec 자바독 태그를 활용하여 문서화 하는것이 좋다.
추상 골격 구현 클래스
디폴트 메서드가 가지고 있는 단점을 극복하기 위해, 인터페이스와 추상 골격 구현 클래스를 함께 제공하는 방식으로 인터페이스와 추상 클래스의 장점을 모두 취하는 방법도 있다.
인터페이스로는 타입을 정의하고, 골격 구현 클래스는 나머지 메서드를 구현한다. 이렇게 해두면 단순히 골격 구현을 확장하는 것만으로 이 인터페이스를 구현하는데 필요한 일이 대부분 완료된다. 바로 이것은 템플릿 메서드 패턴이라고 부른다.
구조상 추상 골격 구현 클래스를 활용 못하는 경우 (다른 클래스 상속)에도 인터페이스를 사용하면 그만이므로, 기존 추상 클래스가 가지고 있단 제약에서도 벗어난다.
추상 골격 구현 클래스 구현하기
- 인터페이스를 살펴 다른 메서드들의 구현에 사용되는 기반 메서드를 선정한다.
- 골격 구현에서 기반 메서드가 추상 메서드가 된다.
- 기반 메서드들을 사용해 직접 구현할 수 있는 메서드는 모두 디폴트 메서드로 제공한다. equals, hashcode와 같은 Object의 메서드는 디폴트 메서드로 제공하면 안된다는 걸 유념하자.
- 만약 인터페이스의 메서드가 모두 기반 메서드나 디폴트 메서드가 된다면, 굳이 골격 구현 클래스를 만들 필요가 없다. 기반 메서드나 디폴트 메서드로 만들지 못한 메서드가 남아있다면, 이 인터페이스를 구현하는 골격 구현 클래스를 만들어 남은 메서드를 작성해 넣는다.
핵심 정리
일반적으로 다중 구현용 타입으로는 인터페이스가 가장 적합하다. 복잡한 인터페이스라 면 구현하는 수고를 덜어주는 골격 구현을 함께 제공하는 방법을 꼭 고려해보자. 골격 구현은 ‘가능한 한’ 인터페이스의 디폴트 메서드로 제공하여 그 인터페이스를 구현한 모든 곳에서 활용하도록 하는 것이 좋다. ‘가능한 한’이라고 한 이유는, 인터페이스에 걸려 있는 구현상의 제약 때문에 골격 구현을 추상 클래스로 제공하는 경우가 더 흔하기 때문이다.
'도서 > 정리' 카테고리의 다른 글
[이펙티브 자바] 아이템21. 인터페이스는 구현하는 쪽을 생각해 설계하라 (0) | 2023.07.11 |
---|---|
[이펙티브 자바] 아이템17. 변경 가능성을 최소화하라 (0) | 2023.07.07 |
[이펙티브 자바] 아이템16. public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 (0) | 2023.07.06 |
[이펙티브 자바] 아이템15. 클래스와 멤버의 접근 권한을 최소화하라 (0) | 2023.07.05 |
[이펙티브 자바] 아이템9. try-finally보다는 try-with-resources를사용하라 (0) | 2023.07.04 |