인터페이스와 구현 클래스가 존재할 때 인터페이스에 새로운 메서드를 추가한다면 구현 클래스에도 새로운
메서드의 구현을 해야 할 것이다. 하지만 메서드를 추가할 때 클래스를 관리할 수 있는 상황이라면 상관이
없겠지만 관리할 수 없는 상황이라면 문제가 발생할 것이다.
위와 같은 상활을 예로 들어, 어떤 한 설계자가 미리 설계한 API가 있고 이를 배포까지 한 상태이다.
배포 후 API를 사용하다 추가해야 할 기능이 생겼고 이를 위해 설계자는 인터페이스에 새로운 메서드를 추가했다.
그런데 만약 메서드 추가 이전에 기존 API를 구현하여 사용하고 있는 사용자의 구현 클래스는 어떻게 될까?
아마 사용자가 직접 구현한 메서드는 동작하지 않을 것이다. 물론 인터페이스에 새로운 메서드를 추가했지만 이를
구현하지 않고 사용한다면 동작은 될 것이다. 하지만 누군가는 새로 추가된 메서드를 구현해서 사용할 수 있기
때문에 미리 에러 발생에 대한 예방을 해야 한다. 이런 문제점을 해결할 수 있는 방법에는 무엇이 있을까?
바로 디폴트 메서드를 활용하면 위와 같은 문제점을 해결할 수 있다.
디폴트 메서드란 말 그대로 default 키워드로 시작되는 메서드로 이를 사용하면 인터페이스 내부에서
메서드 구현이 가능해지며 이를 상속받은 구현 클래스는 메서드를 별도로 구현하지 않아도
디폴트 메서드를 사용할 수 있다.
이런 디폴트 메서드를 위와 같은 상황에 접목시키면 문제를 쉽게 예방할 수 있다.
디폴트 메서드가 정의된 인터페이스를 구현 클래가 상속받으면 인터페이스의 기본 구현을 그대로
상속하므로 인터페이스에 종속되지 않고 자유롭게 새로운 메서드를 추가할 수 있다. 또한 디폴트 메서드는
다중 상속 동작이 가능하기 때문에 유연성을 제공하면서 프로그램 구성에 도움을 준다
디폴트 메서드가 낯설게 느껴질 수 있지만 우리가 자주 사용하는 인터페이스에도
이러한 디폴트 메서드가 많이 사용되고 있다. 그 예로는 List 인터페이스의 sort 메서드가 있다.
- List 인터페이스 내 sort default 메서드
- sort 메서드가 기본적으로 제공하는 기능에 대한 설명
디폴트 메서드 활용 패턴
디폴트 메서드를 이용하는 방식에는 두가지가 있다
1. 선택형 메서드
인터페이스를 구현하는 클래스에서 메서드 내용이 비어있는 경우가 있는데 이러한 예로 Iterator 인터페이스의
remove 메서드가 있다. remove 메서드는 Iterator의 메서드 중 자주 사용되지 않기 때문에 따로 메서드를 구현
하지 않고 디폴트 메서드로 기본 구현 제공하는 형태이다. 이러한 방법을 통해 불필요한 코드 제거가 가능하다.
2. 동작 다중 상속
추상 클래스와 다르게 인터페이스는 여러개 상속받아 구현할 수 있다.
예로 ArrayList 클래스는 한개의 추상 클래스와 네 개의 인터페이스를 상속받고 있는데 여러 인터페이스를
상속받을 수 있으므로 여러 인터페이스 내에 구현된 디폴트 메서드 또한 자동으로 사용할 수 있게 된다.
ArrayList가 상속 받는 추상 클래스 및 인터페이스
그런데 만약 두 개 이상의 인터페이스에서 같은 디폴트 메서드를 구현하고 있다면
메서드 실행의 우선순위는 어떻게 될까? 이는 자바가 컴파일을 할 때 규칙을 가진다.
해석 규칙
1) 구현 클래스 내에서 정의한 메서드가 디폴트 메서드보다 우선권을 가진다.
2) 1번 이외에 상황에서는 서브 인터페이스가 우선순위를 가진다. 즉 B 인터페이스가 A 인터페이스를 상속받는다면
B가 서브 인터페이스가 되고 B의 디폴트 메서드가 우선권이 된다.
3) 만약 1, 2 번 과정을 거쳤는데도 우선순위가 정해지지 않았다면 인터페이스들을 상속받는
구현 클래스가 명시적으로 디폴트 메서드를 오버라이드하고 호출해야 한다.
이 3가지 외에 여러 예외 상황이 있는데 (2번에서 서브 인터페이스가 없고 동등한 상태의 인터페이스일 때)
이러한 경우 자바 컴파일러가 에러를 발생시킨다.
이러한 에러는 자바 8에서 지원하는 super를 사용하여 해결할 수 있는데 super를 통해
사용할 인터페이스와 디폴트 메서드를 지정하는 것이 가능하다.
방법: (인터페이스 명).super.(디폴트 메서드 명)
Reference
참고 도서명: 모던 자바 인 액션
'book > modern java in action' 카테고리의 다른 글
Chapter 16 CompletableFuture : 안정적 비동기 프로그래밍 (0) | 2023.02.25 |
---|---|
Chapter 15 CompletableFuture와 리액티브 프로그래밍 컨셉의 기초 (부제: 쓰레드를 통한 병렬 처리와 쓰레드 풀의 정의 및 기능) (0) | 2023.02.20 |
Chapter 11 null 대신 Optional 클래스 (0) | 2023.02.04 |
Chapter 10 람다를 이용한 도메인 언어(DSL, domain-specific languages) (0) | 2023.01.27 |
Chapter 9 리팩터링, 테스팅, 디버깅 (전략 디자인 패턴의 리팩터링) (0) | 2023.01.23 |
댓글