메서드 구현을 포함하는 인터페이스를 정의함. 두 가지 방법이 있음.
- 인터페이스 내부에 정적 메서드 사용
- 인터페이스의 기본 구현을 제공할 수 있도록 디폴트 메서드 기능 사용
Java8에서 새로 추가된 List interface의 sort 메서드는 default 메서드임.
default void sort(Comparator<? super E> c) {
Collections.sort(this, c);
}
추상 클래스와의 차이점
추상 클래스와 디폴트 메서드는 둘 다 바디를 포함하는 메서드를 정의할 수 있다는 공통점이 있음. 하지만, 이는 엄연히 다름.
- 클래스는 하나의 추상 클래스만 상속받을 수 있지만, 인터페이스는 여러 개 구현할 수 있음.
- 추상 클래스는 인스턴스 변수로 공동 상태를 가질 수 있음. 하지만 인터페이스는 인스턴스 변수를 가질 수 없음.
인터페이스를 구현하는 클래스에서 메서드의 내용이 비어 있는 상황이 많음.
→ 잘 안 쓰는 메서드는 디폴트 메서드를 사용하여 선택적으로 구현하도록 함.
자바에서 클래스는 한 개의 다른 클래스만 상속할 수 있지만 인터페이스는 여러 개 구현할 수 있음.
그러므로, 디폴트 메서드를 이용하여 불가능 했던 동작 다중 상속을 할 수 있음.
상속으로 코드 재사용 문제를 해결하지만, 한 개의 메서드를 재사용하려고 100개의 메서드와 필드가 정의되어 있는 클래스를 상속받는 것은 좋지 않음. 이럴 때는 델리게이션 Delegation을 사용함. 이는 멤버 변수를 이용해서 클래스에서 필요한 메서드를 직접 호출하는 메서드를 말함. 이 규칙을 디폴트 메서드에도 적용할 수 있음.
final class는 핵심 기능을 바꾸지 못하도록 막음. (예: String class)
같은 시그니처를 갖는 디폴트 메서드를 상속받으면 어떡할까? Java8은 이러한 문제에대한 해결 규칙을 제공함.
다른 클래스나 인터페이스로부터 같은 시그니처를 갖는 메서드를 상속받을 때 이 규칙을 따라야 함.
- 클래스가 항상 이긴다. 클래스나 슈퍼클래스에서 정의한 메서드가 디폴트 메서드보다 우선이다.
- 1번 규칙 이외의 상황에서는 서브 인터페이스가 이긴다. 상속 관계를 갖는 인터페이스에서 같은 시그니처를 갖는 메서드를 정의할 때는 서브 인터페이스가 이긴다. 즉, B가 A를 상속받는다면 B가 A를 이긴다.
- 여전히 디폴트 메서드의 우선순위가 결정되지 않았다면, 여러 인터페이스를 상속받는 클래스가 명시적으로 디폴트 메서드를 오버라이드하고 호출해야 한다.