Java8 디폴트 메서드

디폴트 메서드를 사용하는 이유는 뭘까?

주로 라이브러리 설계자들이 사용한다. 디폴트 메서드를 이용하면 자바 API의 호환성을 유지하면서 라이브러리를 바꿀 수 있다. 디폴트 메서드가 없던 시절에는 인터페이스에 메서드를 추가하면서 여러 문제가 발생했다. 인터페이스에 새로 추가된 메서드를 구현하도록 인터페이스를 구현하는 기존 클래스를 고쳐야 했기 때문이었다. 본인이 직접 인터페이스와 이를 구현하는 클래스를 관리할 수 있는 상황이라면 이 문제를 어렵지 않게 해결 할 수 있지만 인터페이스를 대중에 공개했을 때는 상황이 다르다. 그래서 default 메서드가 탄생한 것이다. 디폴트 메서드를 이용하면 인터페이스의 기본 구현을 그대로 상속하므로 인터페이스에 자유롭게 새로운 메서드를 추가할 수 있게 된다.

동작 다중 상속

디폴트 메서드를 이용하면 기존에는 불가능했던 동작 다중 상속 기능도 구현할 수 있다. 그림에서 보는 것처럼 클래스는 다중 상속을 이용해서 기존 코드를 재사용할 수 있다.

자바에서는 클래스는 한개의 다른 클래스만 상속할 수 있지만 인터페이스는 여러개 구현할 수 있다.

자바8에서는 인터페이스가 구현을 포함할 수 있으므로 클래스는 여러 인터페이스에서 동작(구현 코드)를 상속받을 수 있다. 다중 동작 상속을 통해서 중복되지 않는 최소한의 인터페이스를 유지한다면 우리 코드에서 동작을 쉽게 재사용하고 조합할 수 있다.

해석규칙

자바8에서는 디폴트 메서드가 추가되었으므로 같은 시그니처를 갖는 디폴트 메서드를 상속받는 상황이 생길 수 있다. 이런 상황에서 어떤 인터페이스의 디폴트 메서드를 사용하게 될까?

public interface A {
    default void hello() {
        System.out.println("hello from a");
    }
}

public interface B {
    default void hello() {
        System.out.println("hello from b ");
    }
}

static class C implements A, B {
    public static void main(String[] args) {
        new C().hello();
    }
}

알아야할 세가지 해결 규칙

  1. 클래스가 항상 이긴다. 클래스나 슈퍼 클래스에서 정의한 메서드가 디폴트 메서드 보다 우선권을 갖는다.
  2. 1번 규칙 외의 상황에서는 서브 인터페이스가 이긴다. 상속관계를 갖는 인터페이스에서 같은 시그니처를 갖는 메서드를 정의할때는 서브 인터페이스가 이긴다. 즉, B가 A를 상속받는 다면 B가 A를 이긴다.
  3. 여전히 디폴트 메서드의 우선순위가 결정되지 않았다면 여러 인터페이스를 상속받는 클래스가 명시적으로 디폴트 메서드를 오버라이드하고 호출해야 한다.

연관 포스트