Java에서 인터페이스(Interface)는 클래스와 비슷하지만, 오직 추상 메소드(abstract method)와 final·static으로 선언된 필드만 가질 수 있다는 점에서 차이가 있습니다.
- 인터페이스는 메소드 원형(method prototype)의 명세(specification)입니다. 프로그래머에게 구현 방향을 제시하거나, 특정 타입의 메소드와 필드가 어떻게 동작해야 하는지에 대한 '계약(contract)'을 정의하고 싶을 때 인터페이스를 사용합니다.
- 클래스가 특정 명세를 따르도록 하려면 해당 인터페이스를 구현(implement)해야 하며, 인터페이스에 선언된 모든 추상 메소드의 본문(body)을 반드시 작성해야 합니다.
- 인터페이스의 모든 추상 메소드를 구현하지 않으면 컴파일 타임 에러가 발생합니다.
인터페이스에 새로운 메소드가 추가되면 어떻게 될까?
기존에 어떤 인터페이스를 사용해 모든 추상 메소드를 구현해 왔다고 가정해 봅시다. 그런데 이후에 그 인터페이스에 새로운 메소드가 추가되면 어떻게 될까요? 이 경우, 새로 추가된 메소드를 각 클래스마다 구현하지 않는 한 해당 인터페이스를 사용하던 모든 클래스는 정상적으로 동작하지 않습니다.
이러한 문제를 해결하기 위해 Java 8부터 디폴트 메소드(default method)가 도입되었습니다.
디폴트 메소드(Default Method)
디폴트 메소드는 '디펜더 메소드(defender method)' 또는 '가상 확장 메소드(virtual extension method)'라고도 불립니다. default 키워드를 사용하여 다음과 같이 정의할 수 있습니다.
default void display() {
System.out.println("This is a default method");
}인터페이스 내에서 특정 메소드의 기본 구현을 한 번 작성해 두면, 이미 해당 인터페이스를 구현하고 있는 클래스들은 이 메소드를 다시 구현할 필요가 없습니다. 즉, 기존 코드의 호환성을 유지하면서 인터페이스를 확장할 수 있게 되는 것입니다.
예제
다음 Java 예제는 디폴트 메소드의 사용법을 보여줍니다.
interface sampleInterface {
public void demo();
default void display() {
System.out.println("This is a default method");
}
}
public class DefaultMethodExample implements sampleInterface {
public void demo() {
System.out.println("This is the implementation of the demo method");
}
public static void main(String args[]) {
DefaultMethodExample obj = new DefaultMethodExample();
obj.demo();
obj.display();
}
}실행 결과
This is the implementation of the demo method This is a default method
위 예제에서 DefaultMethodExample 클래스는 추상 메소드인 demo()만 구현했습니다. 그럼에도 불구하고 display() 메소드를 호출하면 인터페이스에 정의된 디폴트 구현이 자동으로 실행되는 것을 확인할 수 있습니다. 이처럼 디폴트 메소드를 활용하면 기존 구현 클래스에 영향을 주지 않으면서 인터페이스에 새로운 기능을 손쉽게 추가할 수 있습니다.