<aside> 📖 이 장의 내용
인터페이스를 구현하는 클래스는 인터페이스에서 정의하는 모든 메서드 구현을 제공하거나 슈퍼클래스의 구현을 상속받아야 한다. 하지만 인터페이스가 바뀌면 인터페이스를 구현했던 모든 클래스의 구현도 고쳐야하기 때문에 문제가 되었다.
자바 8에서는 이 문제를 해결하기 위해 기본 구현을 포함하는 인터페이스를 정의하는 두 가지 방법을 제공한다.
디폴트 메서드를 사용하면 자동으로 인터페이스를 구현하는 클래스에 메서드가 상속된다.
다음은 List
인터페이스에 새로 추가된 sort
메서드이다.
default void sort(Comparator<? super E> c) {
Collections.sort(this, c);
}
반환형식 void
앞의 default
키워드는 해당 메서드가 디폴트 메서드임을 가리킨다.
여기서 sort
메서드는 Collections.sort
메서드를 호출한다.
이 새로운 디폴트 메서드 덕분에 리스트에 직접 sort를 호출할 수 있게 되었따.
List<Integer> numbers = Arrays.asList(3, 5, 1, 2, 6);
numbers.sort(Comparator.naturalOrder())://sort는 List 인터페이스의 디폴트 메서드다.
naturalOrder()
는 자연순서(표준 알파벳 순서)로 요소를 정렬할 수 있도록 Comparator
객체를 반환하는 Comparator
인터페이스에 추가된 새로운 정적 메서드다.
우리가 자주 사용했던 strim()
메서드는 내부적으로 StreamSupport.stream
이라는 메서드를 호출해서 스트림을 반환한다. stream()
메서드의 내부에서는 Collection
인터페이스의 다른 디폴트 메서드 spliterator
도 호출한다.
<aside> ❓ 이렇게 되면 결국 인터페이스가 아니라 추상 클래스이지 않나? → 인터페이스와 추상 클래스는 같은 점이 많아졌지만 여전히 다른 점도 있다. (곧 나옴) 또한 디폴 메서드를 사용하는 이유는 뭘까? → 디폴트 메서드는 주로 라이브러리 설계자들이 사용한다. → 디폴트 메서드를 이용하면 자바 API의 호환성을 유지하면서 라이브러리를 바꿀 수 있다는 큰 장점이 있다.
</aside>
디폴트 메서드가 없던 시절엔 인터페이스에 메서드를 추가하면서 여러 문제가 발생했다. 인터페이스에 새로 추가된 메서드를 구현하도록 인터페이스를 구현한 기존 클래스를 고쳐야 했기 때문이었다. 본인이 직접 구현하고 유지보수까지 한다면 상관없지만 다른 사람이 활용하고 유지보수한다면, 이건 끔찍한 상황인 것이다. 그래서 디폴트 메서드가 나왔다. ( 위 내용으론 뭔지 모르겠는데? ) → 즉, 디폴트 메서드를 이용하면 인터페이스의 기본 구현을 그대로 상속하므로 인터페이스에 자유롭게 새로운 메서드를 추가할 수 있게 되기 때문이다.
→ 또한, 디폴트 메서드는 다중 상속 동작이라는 유연성을 제공하면서 프로그램 구성에 도움을 준다.
(이는, 이제 클래스는 여러 디폴트 메서드를 상속받을 숫 있게 되었다는 말이다)