💡 이 장의 내용
- 디폴트 메서드란 무엇인가?
- 진화하는 API가 호환성을 유지하는 방법
- 디폴트 메서드의 활용 패턴
- 해결 규칙
이 장은 디폴트 메서드에 대해 설명한다.
디폴트 메서드란 무엇일까?
디폴트 메서드는 인터페이스 안에서 쓰이는데, 나오게 된 배경을 알면 더 이해가 쉽다. 디폴트 메서드는 인터페이스를 고칠 때 확장성을 제공하기 위해 만들어졌다고 볼 수 있다. 정확히 말하면 인터페이스를 수저어할 때 이전에 해당 인터페이스를 구현했던 모든 클래스의 구현을 고치지 않고 새로운 기능을 추가할 수 있게 하려고 만들어진 것이다.
++같은 기능을 하는 정적 메서드도 있다.
디폴트 메서드 | 정적 메서드 | |
선언 위치 | 인터페이스 안에 선언 | 인터페이스 안에 선언 |
default 키워드 필요 | 필요함 | 필요 없음 (static만 쓰면 됨) |
인스턴스 필요 여부 | 인스턴스가 필요함 (구현체 객체로 호출) | 인스턴스 없이 호출 (클래스처럼 인터페이스명으로 호출) |
오버라이드 가능 여부 | 구현 클래스에서 오버라이드 가능 | 오버라이드 불가 (상속 대상 아님) |
용도 | "기본 동작 제공" (상속+확장 목적) | "공용 유틸리티 기능" 제공 (helper처럼) |
호출 방법 | 구현 객체.default메소드() | 인터페이스명.정적메소드() |
이와 같은 방식으로 추가된 두 가지 예로 List 인터페이스의 sort와 Collection 인터페이스의 stream 메서드가 있다.
13.1 변화하는 API
앞서 설명한 내용처럼 인터페이스 API를 바꾸는 것이 왜 어려운지 이 절에서 설명한다.
인터페이스에 함수 하나를 추가하게 되면, 해당 인터페이스를 구현하는 모든 클래스는 추가된 메서드를 구현해야 한다.
인터페이스에 새로운 메서드를 추가하면 바이너리 호환성은 유지되지만 언젠가 누군가가 해당 메서드를 사용하도록 코드를 바꾼다면 런타임에 에러가 발생하게 된다.
*) 바이너리 호환성: 새로 추가된 메서드를 호출하지만 않으면 새로운 메서드 구현이 없이도 기존 클래스 파일 구현이 잘 동작한다는 의미
13.2 디폴트 메서드란 무엇인가?
공개된 API에 새로운 메서드를 추가하면 기존 구현에 어떤 문제가 생기는지 살펴봤다.
자바 8에서는 호환성을 유지하면서 API를 바꿀 수 있도록 새로운 기능인 디폴트 메서드를 제공한다.
public interface Sized {
int size();
default boolean isEmpty() {
return size() == 0;
}
}
이제 Sized를 구현하는 모든 클래스는 isEmpty()의 구현도 상속받는다.
즉, 인터페이스에 디폴트 메서드를 추가하면 소스 호환성이 유지된다.
13.3 디폴트 메서드 활용 패턴
디폴트 메서드를 이용하는 두 가지 방식이 있다.
선택형 메서드(optional method)와 동작 다중 상속(multiple inheritance of behavior)을 설명한다.
13.3.1 선택형 메서드
Iterable 인터페이스를 보면 remove기능이 에러를 던지도록 처리되어있다.
사용자들이 remove 기능은 잘 사용하지 않으므로 구현하지 않은건데
디폴트 메서드를 이용하면 필요한 클래스에서만 remove 같은 메서드에 오버라이드를 통해 기본 구현을 제공할 수 있으므로 불필요한 코드의 구현을 막을 수 있다.
13.3.2 동작 다중 상속
디폴트 메서드를 이용하면 기존에는 불가능했던 동작 다중 상속 기능도 구현할 수 있다.
예를 들어 움직일 수 있고, 회전할 수 있으며, 크기를 조절할 수 있는 각각의 인터페이스의 구현을 상속받아 하나의 괴물 클래스를 만들 수 있는 것이다.
13.4 해석 규칙
다른 클래스나 인터페이스로부터 같은 시그니처를 갖는 메서드를 상속받을 때는 세 가지 규칙을 따라야 한다.
1. 클래스가 항상 이긴다. 클래스나 슈퍼클래스에서 정의한 메서드가 디폴트 메서드보다 우선권을 갖는다.
2. 1번 규칙 외의 상황에서는 서브 인터페이스가 이긴다. 상속 관계를 갖는 인터페이스에서 같은 시그니처를 갖는 메서드를 정의할 때는 서브인터페이스가 이긴다. 즉, B가 A를 상속받는다면 B가 A를 이긴다.
3. 여전히 디폴트 메서드의 우선순위가 결정되지 않았다면 여러 인터페이스를 상속받는 클래스가 명시적으로 디폴트 메서드를 오버라이드하고 호출해야 한다.
'Book > 모던 자바 인 액션' 카테고리의 다른 글
[모던 자바 인 액션] Chapter 12. 새로운 날짜와 시간 API (0) | 2025.01.12 |
---|---|
[모던 자바 인 액션] Chapter 11. null 대신 Optional 클래스 (2) (1) | 2024.11.20 |
[모던 자바 인 액션] Chapter 11. null 대신 Optional 클래스 (1) (2) | 2024.11.15 |
[모던 자바 인 액션] Chapter 10.람다를 이용한 도메인 전용 언어 (1) (1) | 2024.11.14 |
[모던 자바 인 액션] Chapter 09. 리팩터링, 테스팅, 디버깅 (2) (4) | 2024.11.12 |