ITEM 20 "추상 클래스보다는 인터페이스를 우선하라"
자바에서는 다중 구현 메카니즘으로 추상 클래스와 인터페이스를 제공하고 있다.
자바8 부터 인터페이스도 default 메서드와 static 메서드를 제공할 수 있게 되어 이제는 두 메카니즘 모두 인스턴스 메서드를 구현 형태로 제공할 수 있다. 자바8 의 인터페이스 기초 영상은 아래를 참고하자.
사실 큰 차이는 없어지고, 추상클래스의 단점만 부각되는 꼴이 되었다.
추상 클래스를 정의한 타입을 구현한 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 하는데 자바가 단일 상속만 지원하다 보니, 추상 클래스 방식은 새로운 타입을 정의하는데 커다란 제약이 있다.
반면, 인터페이스는 선언된 메서드들을 모두 구현하고 일반 규약을 잘 지킨다면 다른 어떤 클래스를 상속해도 같은 타입으로 취급된다. 그래서 기존 클래스에 새로운 인터페이스를 구현할 수 있다는 장점이 있다. 인터페이스의 장점에 대해 더 자세히 알아보자.
인터페이스의 장점
1 . 인터페이스는 믹스인 정의에 알맞다.
mixin 은 클래스 구현 타입으로 '주된 타입' 외에 선택적 기능을 혼합하여 제공함을 뜻한다. 예를 들어 Comparable 은 자신을 구현한 클래스의 인스턴스끼리는 순서를 정할 수 있다고 선언하는 믹스인 인터페이스이다. 추상 클래스는 기존 클래스를 덮어 씌워 계층 구조를 이루어야 하기 때문에 부가 기능을 혼합해서 제공하기가 힘들다. (상속은 완벽히 IS-A 관계를 가져야 함)
2 . 인터페이스로 계층구조가 없는 타입 프레임워크를 만들 수 있다.
타입을 계층적으로 정의하는 상속 구조가 개념들을 구조적으로 표현할 수 있지만, 상속은 캡슐화를 해칠 수 있다.
반면에 인터페이스는 아래와 같이 부가 기능들을 섞어 새로운 타입으로 만들 수 있다. 상속처럼 다른 클래스로 구현할 때 어떠한 제약이 없다.
interface Singer {
AudioClip sing(Song s);
}
interface SongWriter {
Song compose(int chartPosition);
}
interface SingerSongwriter extends Singer, SongWriter {
AudioClip strum();
void actSensitive();
}
같은 구조를 추상 클래스로 만들었다면 가능한 조합 전부를 각각의 클래스로 정의한 고도비만 계층구조가 만들어진다.
완벽한 IS-A 관계에 있어야 하므로, 속성이 N 개라면 지원해야 할 조합의 갯수는 2^N 개가 된다.
인터페이스의 디폴트 메서드
인터페이스 규약이 바뀌어 새로운 메서드를 추가 선언해야 된다고 한다면, 그 인터페이스를 구현한 모든 클래스에서 그 해당 메서드를 추가 구현해야 한다. 이런 문제점 때문에 자바 8 부터 디폴트 메서드를 제공하고 있다. 인터페이스 메서드 중 구현 방법이 명백한 것이 있다면 그 구현을 디폴트 메서드로 제공해도 된다. 참고로, 많은 인터페이스들이 equals 와 hashCode 같은 Object 의 메서드를 정의하는데 이들을 디폴트 메서드로 제공하면 안 된다.
인터페이스의 단점
인터페이스는 인스턴스 필드를 가질 수 없고 public 이 아닌 정적 멤버도 가질 수 없다.
인터페이스 + 추상 골격 구현 = 템플릿 메서드 패턴
인터페이스의 장점과 추상 클래스의 장점을 모두 취한 패턴이 템플릿 메서드 패턴이다. 인터페이스로 타입을 정의하고 골격 구현 클래스에서 나머지 메서드들까지 구현하면서 골격 구현을 확장하는 것만으로 인터페이스를 구현하게 되버리고 쉬어진다.
"다중 구현 타입으로는 인터페이스가 가장 적합하다.
복잡한 인터페이스라면, 구현한는 수고를 덜어주는 골격 구현 클래스를 함께 고려해보자."
'독후감 > Effective JAVA' 카테고리의 다른 글
[Effective JAVA] 22 "인터페이스는 타입을 정의하는 용도로만 사용하라" (0) | 2022.05.17 |
---|---|
[Effective JAVA] 21 "인터페이스는 구현하는 쪽을 생각해 설계하라" (0) | 2022.05.12 |
[Effective JAVA] 19 "상속을 고려해 설계하고 문서화하라" (0) | 2022.05.10 |
[Effective JAVA] 18 "상속보다는 컴포지션을 사용하라" (0) | 2022.05.10 |
[Effective JAVA] 17 "변경 가능성을 최소화하라" (0) | 2022.05.10 |