-
item 20 추상 클래스보다는 인터페이스를 우선하라책/이펙티브 자바 2022. 3. 8. 23:39
ITEM 20 추상 클래스보다는 인터페이스를 우선하라
인터페이스 사용시 장점
- 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해 넣을 수 있다
- 인터페이스가 요구하는 메서드를 추가하고, 클래스 선언부에 implements 만 적어주면 끝
- 추상 클래스는 계층구조상 같은 조상을 바라봐야 해서 기존 클래스에 추가하기가 어렵다
- 새로 추가된 추상 클래스의 모든 하위 클래스가 상속하게 되는것
- 인터페이스는 믹스인 정의에 안성맞춤이다
- 믹스인 : 클래스가 구현할 수 있는 타입
- 대상 타입의 주된 기능에 선택적 기능을 제공하는것
- 추상 클래스에는 위와 동일한 이유로 믹스인을 정의 할 수 없다
- 자바에서 일반 클래스는 단일상속만 지원하여 클래스 계층 구조에서는 믹스인을 삽입하기에 적절한 위치가 없음
- 믹스인 : 클래스가 구현할 수 있는 타입
- 인터페이스로는 계층구조가 없는 타입 프레임워크를 만들 수 있다
- 타입을 인터페이스로 정의함으로써 다중상속이 가능해져 확장과 추가가 용이해진다
- 래퍼 클래스와 함께 사용하면 인터페이스는 기능을 향상 시키는 안전하고 강력한 수단이 된다
- 타입을 추상클래스로 정의하면 해당 타입에 기능을 추가하려면 상속을 사용해야 한다
- 상속해서 만든 클래스는 활용도가 떨어지고 깨지기 쉽다
- 타입을 추상클래스로 정의하면 해당 타입에 기능을 추가하려면 상속을 사용해야 한다
인터페이스의 메서드 중 구현 방법이 명확한게 있다면 디폴트 메서드를 고려해보자
- 디폴트 메서드를 제공할 때는 상속하려는 사람을 위한 설명을 @implSpec 자바독 태그를 붙여 문서화 해야한다
- 디폴트 메서드의 제약
- equals, hashCode 등의 Object 메서드를 디폴트 메서드로 제공해서는 안된다
- 자기가 만들지 않은 인터페이스에는 디폴트 메서드를 만들 수 없다
- 인터페이스는 인스턴스 필드를 가질 수 없고 public이 아닌 정적 멤버도 가질 수 없다(private 정적 메서드는 예외)
추상 골격 구현 클래스를 함께 제공
- 인터페이스와 추상 클래스의 장점을 모두 취할 수 있다
- 타입을 인터페이스로 정의하고 (필요하다면 디폴트 메서드도 제공) 골격 구현 클래스는 나머지 메서드들까지 구현한다
- 단순 골격 구현을 확장하는 것 만으로 해당 인터페이스를 구현하는게 쉬워진다
- 이렇게 하면 대부분의 구현이 끝나지만 꼭 이렇게 해야 되는것은 아니다
- 구조상 골격 구현을 확장하는게 힘들다면 인터페이스를 직접 구현해도 디폴트 메서드의 장점을 누릴 수 있다
- 이게 템플릿 메서드 패턴이다
- 관례상 Abstract를 접두어로 쓴다
- 골격 구현 클래스는 추상 클래스처럼 구현을 도와주지만 추상 클래스로 타입을 정의할 때 생기는 제약에 자유롭다
- 인터페이스를 구현한 클래스에서 해당 골격 구현을 확장한 private 내부 클래스를 만들고 각 메서드 호출을 내부 클래스의 인스턴스에 전달하여 골격 구현 클래스를 우회적으로 이용도 가능하다
- 이런 방식을 시뮬레이트한 다중상속이라 부른다
- 다중상속의 장점은 취하고 단점은 피하게 해준다
골격 구현의 작성
- 인터페이스에서 다른 메서드의 구현에 사용되는 기반 메서드를 고른다
- 이 메서드들이 추상 메서드가 된다
- 기반 메서드들을 사용해 직접 구현할 수 있는 메서드를 모두 디폴트 메서드로 제공
- 디폴트 메서드의 제약에 있는 Object의 메서드들은 안된다
- 만약 인터페이스의 모든 메서드가 기반 메서드와 디폴트 메서드가 된다면 골격 구현 클래스를 별도로 만들 필요는 없다
- 기반 메서드나 디폴트 메서드로 만들지 못한 메서드가 있다면 이 인터페이스를 구현하는 골격 구현 클래스를 만들어 남은 메서드를 넣는다
- 골격 구현 클래스에는 필요하다면 public이 아닌 필드나 메서드도 추가 가능하다
- 골격 구현은 기본적으로 상속해서 사용한다고 생각하기 때문에 상속시 고려하는 설계와 문서화가 필수다
- 단순 구현은 골격 구현의 작은 변종이다
- 상속을 위해 인터페이스를 구현한건 같지만 추상 클래스가 아니다
- 동작하는 가장 단순한 구현이다
- 그냥 사용해도 되고 확장해도 된다
일반적으로 다중 구현용 타입은 인터페이스가 적합하다
복잡한 인터페이스라면 골격 구현을 함께 제공하는 방법도 고려하자
골격 구현은 가능한 인터페이스의 디폴트 메서드로 제공하여 해당 인터페이스를 구현한 모든 곳에서 활용하도록 하는게 좋다
위에서 가능한 이라고 한 이유는 구현상의 제약 때문에 골격 구현을 추상 클래스로 제공하는 경우가 더 흔하기 때문
'책 > 이펙티브 자바' 카테고리의 다른 글
item 22 인터페이스는 타입을 정의하는 용도로만 사용하라 (0) 2022.03.10 item 21 인터페이스는 구현하는 쪽을 생각해 설계하라 (0) 2022.03.09 item 19 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라 (0) 2022.03.07 item 18 상속보다는 컴포지션을 사용하라 (0) 2022.03.04 item 17 변경 가능성을 최소화하라 (0) 2022.03.03 - 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해 넣을 수 있다