디폴트 메소드(Default Method) 또는 기본 메소드는 Java 8에서 추가된 기능 중 하나입니다.

디폴트 메소드는 인터페이스의 메소드에서 기본적으로 구현 기능을 제공하는 것인데요, 자세히 알아보겠습니다.

1. 디폴트 메소드(Default Method)

디폴트 메소드는 아래와 같이 인터페이스에서 메소드를 구현하는 것을 말합니다.

  • 이전에는 인터페이스는 메소드를 선언만 할 수 있고, 구현할 수 없었음. 구현은 이것을 구현(implements)하는 클래스에서 할 수 있었음
  • 인터페이스에서 메소드 선언과 동시에 기본 구현을 정의할 수 있음
public interface MyInterface {
    // 일반 메소드
    void regularMethod();

    // 디폴트 메소드
    default void defaultMethod() {
        // 구현
    }
}

디폴트 메소드는 아래와 같은 특징이 있습니다. 아래에서 각 특징에 대해서 알아보겠습니다.

  • 기본 구현 제공: 인터페이스에 기본 구현을 제공합니다. 이로 인해 해당 인터페이스를 구현(implements)하는 클래스에서 디폴트 메서드를 구현하지 않아도 됨
  • 기존 코드와의 호환성: 새로운 메서드를 인터페이스에 추가할 때, 이미 해당 인터페이스를 구현하고 있는 클래스에 영향을 주지 않고 새로운 기능을 추가할 수 있음
  • 다중 상속 지원: 다중 상속을 지원하여, 여러 인터페이스를 구현하여 동일한 메소드를 갖고 있을 때 충돌을 방지할 수 있음

2. 특징: 기본 구현 제공

지금까지 소개한 것처럼, 디폴트 메소드는 인터페이스에 기본 구현을 제공합니다.

아래 예제를 보면 기본 메소드를 어떻게 사용하는지 알 수 있습니다.

  • MyInterface의 regularMethod()는 메소드 선언만 하였고, MyClass에서 메소드를 구현함
  • MyInterface의 defaultMethod()는 인터페이스에서 메소드 선언과 구현을 모두 했음, MyClass에서 구현할 필요 없음
public class Example {

    interface MyInterface {
        void regularMethod();

        default void defaultMethod() {
            System.out.println("This is a default method.");
        }
    }

    static class MyClass implements MyInterface {
        public void regularMethod() {
            System.out.println("This is a regular method.");
        }
    }

    public static void main(String[] args) {

        MyClass obj = new MyClass();
        obj.regularMethod();
        obj.defaultMethod();
    }
}

Output:

This is a regular method.
This is a default method.

3. 특징: 기존 코드와의 호환성

기본 메소드를 사용하는 이유 중에 하나는, 인터페이스에 새로운 메소드를 추가할 때 기존 코드와의 호환성을 유지해야하는 경우입니다.

예를 들어, 아래와 같은 상황은 디폴트 메소드를 사용하여 해결할 수 있습니다.

  • MyInterface에 regularMethod()defaultMethod() 함수만 있었고, 라이브러리로 배포되어 다른 프로그램에서 사용하고 있었음
  • MyInterface에 newMethod()를 추가해야 하는 상황이 생김, 메소드를 추가하면 이 인터페이스를 사용하는 다른 프로그램의 클래스에서 모두 구현해야해서, 프로그램을 수정하고 다시 컴파일해야 함.
  • 디폴트 메소드를 이용하여 인터페이스에서 newMethod() 메소드를 구현하면, 다른 프로그램에서 구현을 추가할 필요가 없음. 즉, 프로그램을 수정할 필요가 없고, 다시 컴파일하지 않아도 됨
public class Example {

    interface MyInterface {
        void regularMethod();

        default void defaultMethod() {
            System.out.println("This is a default method.");
        }

        default void newMethod() {
            System.out.println("This is a new default method.");
        }
    }

    static class MyClass implements MyInterface {
        public void regularMethod() {
            System.out.println("This is a regular method.");
        }
    }

    public static void main(String[] args) {

        MyClass obj = new MyClass();
        obj.regularMethod();
        obj.defaultMethod();
        obj.newMethod();
    }
}

Output:

This is a regular method.
This is a default method.
This is a new default method.

4. 특징: 다중 상속 지원

디폴트 메소드는 다중 상속을 지원하며, 여러 인터페이스를 구현하면서 동일한 이름의 메소드를 갖고 있을 때, 클래스에서 메소드를 오버라이드하여 재정의하거나 어떤 인터페이스의 기본 구현을 사용할지 선택할 수 있습니다.

  • Penguin 클래스에 makeSound()를 오버라이드하지 않으면 어떤 기본 메소드를 호출할지 몰라서 컴파일 에러 발생
  • Penguin 클래스에서 makeSound() 오버라이드하여 새로 정의하거나, 어떤 인터페이스의 기본 구현을 사용할지 구현할 수 있음
  • 아래 예제는 Penguin에서 Animal과 Bird의 makeSound()를 모두 호출하도록 구현
public class Example {

    interface Animal {
        default void makeSound() {
            System.out.println("Some sound");
        }
    }

    interface Bird {
        default void makeSound() {
            System.out.println("Chirp chirp");
        }
    }

    static class Penguin implements Animal, Bird {
        @Override
        public void makeSound() {
            // 메소드를 재정의 하거나, 어떤 인터페이스의 구현을 호출할지 선택
            Animal.super.makeSound();
            Bird.super.makeSound();
        }
    }

    public static void main(String[] args) {

        Penguin penguin = new Penguin();
        penguin.makeSound();
    }
}

Output:

Some sound
Chirp chirp