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