Programming/JAVA
[Effective JAVA] item 20 : 추상 클래스 보다는 인터페이스를 우선하라
sky Jeong
2021. 7. 3. 16:18
서론
- 자바의 다중 구현 메커니즘: 인터페이스, 추상 클래스
- 둘의 차이
- 추상 클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 함
- 자바는 단일 상속만 지원하기 때문
- 둘의 차이
인터페이스
- 기존 클래스에 쉽게 새로운 인터페이스 구현 가능
- 인터페이스가 요구하는 메서드를 추가하고, 클래스 선언에 implements 구문만 추가하면 됨
- 인터페이스는 믹스인(mixin) 정의에 안성맞춤
- 믹스인(mixin)
- 대상 타입의 주된 기능에 선택적 기능을 혼합(mix in)하는 것
- 클래스가 구현할 수 있는 타입
- 원래 주된 타입 외에 특정 선택적 행위를 제공하다고 선언하는 효과를 줌
- 추상 클래스는 기존 클래스에 덧씌울 수 없어 믹스인 정의가 불가함
=> 클래스는 두 개의 부모를 가질 수 없고, 클래스 계층 구조에 믹스인 삽입하기에 합리적 위지가 없기 떄문
- 믹스인(mixin)
- 인터페이스로 계층구조가 없는 프레임워크를 만들 수 있음
- 타입을 계층적으로 정의하면 수많은 개념의 구조적 표현이 가능하나 현실에서 계층 구조를 엄격히 구분하기 어려운 개념이 존재
- 내가 이해하기에..
- 인터페이스는 is able to 를 주로 표현을 많이하는데
- 이로 계층구조가 불명확한 현실 세계의 개념을 명확히 적용할 수 있기에 그런 것으로 보임
- 기능을 향상시키는 안전하고 강력한 수단
- 래퍼 클래스 관용구(item 18)과 함께 사용시 인터페이스는 기능을 향상시키는 안전하고 강력한 수단이 됨
- 타입을 추상 클래스로 정의할 경우 그 타입에 기능을 추가하는 방법은 상속 밖에 없음
- 이때 상속해 만든 클래스는 래퍼 클래스보다 활용도가 떨어지고 깨지기 더 쉬움
- 인터페이스 메서드 중 구현 방법이 명확한 것이 존재한다면, 이는 디폴트 메서드로 제공할 수 있음
- 이는 책의 코드 21-1 removeIf 메서드를 보면됨
- Default 메서드를 제공할 때는 상속하려는 사람을 위한 설명을 @implSpec 자바 독 태그를 붙여 문서화해야 함
(item 19)- Defalt 메서드에 제약이 존재함
- equals, hashCode는 디폴트 메서드로 정의해서는 안됨
- 인터페이스는 인스턴스 필드를 가질 수 없음
- public이 아닌 정적 멤버를 가질 수 없음 (단, private 정적 메서드는 예외)
- 직접 개발하지 않은 인터페이스에 디폴트 메서드를 추가해서는 안 됨
- Defalt 메서드에 제약이 존재함
- 인터페이스와 추상 골격 구현(skeletal implementatin) 클래스를 함께 재공해 인터페이스와 추상 클래스 장점을 모두 취할 수 있음
- 템플릿 메서드 패턴
- 인터페이스 = 타입 정의
- 필요시 디폴트 메서드 함께 제공
- 그리고 골격 구현 클래스는 나머지 메서드들까지 구현
- 위 처럼 구현할 경우 단순 골격 구현을 확장하는 것만으로 이 인터페이스를 구현하는데 필요한 일이 대부분 완료됨
이를 위에 언급된 '템플릿 메서드 패턴'이라 함 - 골격 구현 클래스 = 'AbstractInterface'
- AbstractCollection, AbstractSet, AbstractList, AbstractMap 각각이 핵심 컬렉션 인터페이스의 골격 구현
- 골격 구현의 작성
- 인터페이스를 사라펴 다른 메서드들의 구현에 사용되는 기반 메서드 선정
- 기반 메서드들이 골격 구현에서 추상 메서드가 됨
- 기반 메서드들을 사용해 직접 구현할 수 있는 메서드를 모두 디폴트 메서드로 제공
(단, equals, hashCode와 같은 Object 메서드는 제공해서는 안 됨) - 만약 메서드 모두 기반 메서드와 디폴트 메서드가 된다면 골격 구현 클래스를 별도로 만들 이유가 없음
- 템플릿 메서드 패턴
- 골격 구현은 기본적으로 상속해 사용하는 걸 가정하기에 아이템 19에서 이야기한 설계 및 문서화 지침을 모두 따라야 함
- 단순 구현은 골격 구현의 작은 변종임,. 이는 그대로 써도 되고 필요에 따라 확장해도 됨.
핵심 정리
- 다중 구현용 타입으로 인터페이스가 가장 적합함
- 복잡한 인터페이스라면 구현 수고를 덜어주는 골격 구현을 함꼐 제공한느 방법을 고려할 것
- 골격 구현은 '가능한 한' 인터페이스의 디폴트 메서드로 제공해 그 인터페이스를 구현한 모든 곳에서 활용하도록 하는 것이 좋음
- 가능한 한이라고 표현한 이유는 인터페이스에 걸려 있는 구현상의 제약 떄문에 골격 구현을 추상 클래스로 제공하는 경우가 더
흔하기 때문
- 가능한 한이라고 표현한 이유는 인터페이스에 걸려 있는 구현상의 제약 떄문에 골격 구현을 추상 클래스로 제공하는 경우가 더