본문으로 건너뛰기

Item20

추상 클래스보다는 인터페이스를 우선하라

1 추상 클래스와 인터페이스

  • 자바가 제공하는 다중 구현 메커니즘은 인터페이스와 추상 클래스 두 가지다

1.1 공통점

  • 인스턴스로 생성이 불가능하다.
  • 선언부만 있는 추상 메서드를 갖는다.
    • 인스턴스 메서드를 구현 형태로 제공할 수 있다.

1.2 차이점

  • 추상 클래스
    • 추상 클래스를 상속받아 기능을 이용하고 확장시켜야한다.
    • 단일 상속만 지원하기 때문에, 다중 클래스 상속이 불가능하다.
  • 인터페이스
    • 구현을 강제해서 구현 객체가 같은 동작을 하도록 보장한다.
    • 구현해야하는 메소드만 구현하면 어떤 클래스를 상속하던 간에 같은 타입으로 취급한다.
    • 여러 인터페이스를 상속이 가능하다.

2 기존 클래스 확장

2.1 기존 클래스에 인터페이스 확장

  • 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해넣을 수 있다
  • 클래스 선언에 implements만 추가하고 인터페이스가 요구하는 메서드만 구현하면 된다
  • 자바 플랫폼에서도 Comparable, Iterable, AutoCloseable 인터페이스가 새로 추가되었을 때 표준 라이브러리의 수 많은 기존 클래스가 이 인터페이스를 구현한 채 릴리스됐다.

2.2 기존 클래스에 추상 클래스 확장

  • 기존 클래스 위에 새로운 추상 클래스를 끼워넣기는 어려운 것이 일반적이다
  • 두 클래스가 같은 추상 클래스를 확장하길 원한다면, 그 추상 클래스는 계층구조상 두 클래스의 공통 조상이어야한다.
  • 만약 Comparable, Iterable, AutoCloseable 인터페이스가 아니라 추상 클래스였다면
    • Comparable하고 Iterable한 새로운 추상 클래스 ComparableAndIterableAbstractClass 만들고
    • Comparable하고 AutoCloseable한 새로운 추상 클래스를 ComparableAndAutoCloseableAbstractClass를 만들고
    • ... 조합의 수 2^n
    • 같은 구조를 클래스로 만드려면 가능한 조합 전부를 각각의 클래스로 정의한 고도비만 계층구조가 만들어진다
    • 흔히 조합 폭발이라고 부르는 현상

2 믹스인 인터페이스

  • 인터페이스는 믹스인 정의에 안성맞춤이다
  • 믹스인
    • 클래스가 구현할 수 있는 타입
    • 믹스인을 구현한 클래스는 원래의 주된 타입 외에도도 특정 기능를 제공한다고 선언하는 효과를 준다
    • 예시) Comparable 믹스인 인터페이스를 구현한 클래스는 해당 클래스의 인스턴스끼리 순서를 정할 수 있다고 선언하는 효과

3 믹스인 추상클래스

  • 추상클래스로는 믹스인을 정의할 수 없다
  • 클래스는 두 부모를 섬길 수 없고, 클래스의 계층구조는 믹스인을 삽입하기 합리적인 위치가 없기 때문
  • 만약 Comparable, Iterable, AutoCloseable 인터페이스가 아니라 추상 클래스였다면
    • Comparable하고 Iterable한 새로운 추상 클래스 ComparableAndIterableAbstractClass 만들고
    • Comparable하고 AutoCloseable한 새로운 추상 클래스를 ComparableAndAutoCloseableAbstractClass를 만들고
    • ... 조합의 수 2^n
    • 같은 구조를 클래스로 만드려면 가능한 조합 전부를 각각의 클래스로 정의한 고도비만 계층구조가 만들어진다
    • 흔히 조합 폭발이라고 부르는 현상

4 추상 골격 구현 클래스

  • 추상 골격 구현 클래스는 인터페이스와 추상 클래스의 장점 모두를 취하는 방법이다.
  • 인터페이스로는 타입을 정의하고, 필요하면 디폴트 메서드 몇개도 함께 제공한다.
  • 그리고 골격 구현 클래스는 나머지 메서들들까지 구현한다.
  • 이렇게 하면 골격 구현을 확장하는 것만으로 이 인터페이스를 구현하는 데 필요한 대부분의 일이 완료된다.
  • 이것은 템플릿 메서드 패턴이라고 한다.

추상 골격 구현 클래스 네이밍

  • 관례상 인터페이스의 이름이 Interface라면 그 골격 구현 클래스의 이름은 AbstractInterface로 짓는다
  • 예시 AbstractCollection, AbstractList, AbstractMap, AbstractSet

참고