본문 바로가기
Programing/Java & Spring

Java Default Method (디펄트 메소드)

by 슈퍼와이비 2023. 9. 8.
반응형
Default Method(디펄트 메소드) 란?

 

Java 인터페이스는 기본적으로 메소드의 시그니처만을 정의하고 구현 내용은 제공하지 않습니다. 그러나 Java 8부터는 인터페이스에 default 메소드를 도입했습니다.

default 메소드는 인터페이스에 기본적으로 구현이 제공되는 메소드입니다. 이러한 메소드는 인터페이스를 구현하는 클래스에서 구현하지 않아도 되며, 기본 구현을 사용할 수 있습니다. default 메소드는 인터페이스의 일부로 포함되므로 클래스가 해당 인터페이스를 구현하면 자동으로 사용할 수 있습니다.

default 메소드는 인터페이스에 새로운 기능을 추가하는 데 사용될 수 있습니다. 이를 통해 인터페이스를 구현하는 모든 클래스에서 해당 메소드를 사용할 수 있습니다. 그러나 default 메소드를 재정의하거나, 구현 클래스에서 다시 구현하는 것도 가능합니다. 이렇게 하면 구현 클래스에서 기본 구현을 재정의하여 특정 동작을 변경하거나 확장할 수 있습니다.

 

다음은 default 메소드를 가진 인터페이스의 예시입니다

public interface MyInterface {
    // 일반 메소드
    void normalMethod();

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


인터페이스에서 default 메소드를 호출하는 코드 예시는 다음과 같습니다

public class MyClass implements MyInterface {
    public void normalMethod() {
        System.out.println("Implementing normalMethod.");
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.normalMethod();   // 출력: Implementing normalMethod.
        obj.defaultMethod();  // 출력: This is a default method.
    }
}

이 예시에서 MyClass는 MyInterface를 구현하고 있으며, normalMethod()를 구현하였습니다. defaultMethod()는 구현하지 않았지만, 인터페이스에서 제공하는 기본 구현이 사용됩니다.

 

 

Default Method의 출현 이유

 

Java 8에서 default 메소드가 도입된 주요 이유는 기존의 인터페이스를 확장하고 변경하기 위한 것입니다. 이전 버전의 Java에서는 이미 인터페이스를 구현하는 클래스들이 있을 경우, 새로운 메소드를 추가하거나 인터페이스를 확장하는 것이 어렵거나 불가능한 상황이었습니다. 이로 인해 새로운 기능을 추가하거나 기존 인터페이스를 수정하는 것이 어려웠습니다.

Java 8 이전에는 인터페이스에 새로운 메소드를 추가하려면 모든 해당 인터페이스를 구현하는 클래스에서 새 메소드를 구현해야 했습니다. 이는 기존 코드를 변경해야 하는 많은 어려움과 호환성 문제를 초래했습니다.

Java 8에서 default 메소드를 도입함으로써 다음과 같은 이점을 얻을 수 있게 되었습니다

 

  1. 역호환성 유지: 기존 인터페이스를 확장하고 새로운 메소드를 추가할 때, 이미 해당 인터페이스를 구현한 클래스들은 새 메소드를 구현하지 않아도 됩니다. 이로써 기존 코드의 역호환성을 유지할 수 있습니다.
  2. 기본 구현 제공: 인터페이스에서 기본 구현을 제공함으로써, 해당 인터페이스를 구현하는 클래스에서 모든 메소드를 재정의할 필요가 없게 되었습니다. 이는 코드를 더 간결하게 만들어주고, 새로운 기능을 추가하기 쉽게 합니다.
  3. 다중 상속 문제 해결: Java는 다중 상속을 지원하지 않습니다. 그러나 default 메소드를 통해 인터페이스에서 다중 상속과 유사한 기능을 제공할 수 있게 되었습니다. 클래스는 여러 인터페이스를 구현하여 다양한 기능을 효과적으로 조합할 수 있습니다.
  4. 라이브러리 확장성: Java 표준 라이브러리의 인터페이스도 default 메소드를 사용하여 새로운 기능을 추가하고, 기존 코드와의 호환성을 유지하면서 업데이트할 수 있습니다.

    이러한 이유로 Java 8에서 default 메소드가 도입되었으며, 이를 통해 Java 언어의 유연성과 기능 확장성이 향상되었습니다.

 

다중 상속 문제 해결

 

Java에서는 클래스가 하나의 클래스만 상속할 수 있기 때문에, 다중 상속을 직접 지원하지 않습니다. 대신, Java에서는 다중 상속과 유사한 효과를 얻기 위해 implements 키워드를 사용하여 여러 인터페이스를 구현할 수 있습니다.

클래스가 인터페이스를 implements하면 해당 클래스는 인터페이스에서 정의된 메소드를 구현해야 합니다. 그러나 Java 8 이후부터는 인터페이스에서 기본(default) 메소드를 제공하면서, 인터페이스를 구현하는 클래스가 해당 메소드를 구현하지 않아도 되게끔 되었습니다. 이것이 인터페이스에서 다중 상속과 유사한 효과를 주는 방법 중 하나입니다.

즉, 여러 인터페이스를 implements하여 클래스에 다양한 기능을 추가하고, 각 인터페이스에서 제공하는 기본(default) 메소드를 사용하여 클래스에 기본 구현을 제공할 수 있습니다. 이렇게 하면 클래스는 여러 인터페이스의 기능을 조합할 수 있고, 다중 상속과 유사한 효과를 얻을 수 있습니다.

 

// 다중 상속과 유사한 기능을 제공하는 인터페이스
interface Flyable {
    default void fly() {
        System.out.println("I can fly!");
    }
}

interface Swimmable {
    default void swim() {
        System.out.println("I can swim!");
    }
}

class Bird implements Flyable {
    // Bird 클래스는 Flyable 인터페이스를 구현하고 있으므로 fly() 메소드를 상속받습니다.
    // Bird 클래스에서 다른 메소드를 구현하지 않아도 fly()를 사용할 수 있습니다.
}

class Fish implements Swimmable {
    // Fish 클래스는 Swimmable 인터페이스를 구현하고 있으므로 swim() 메소드를 상속받습니다.
    // Fish 클래스에서 다른 메소드를 구현하지 않아도 swim()을 사용할 수 있습니다.
}

class Duck implements Flyable, Swimmable {
    // Duck 클래스는 Flyable과 Swimmable 인터페이스를 모두 구현하고 있으므로 fly()와 swim() 메소드를 상속받습니다.
    // Duck 클래스에서 다른 메소드를 구현하지 않아도 fly()와 swim()을 모두 사용할 수 있습니다.
}

이 예시에서 Flyable과 Swimmable 인터페이스는 각각 fly()와 swim() 메소드를 기본 구현으로 제공하고 있습니다. 그리고 Bird, Fish, Duck 클래스는 각 인터페이스를 구현하고 있으며, 해당 인터페이스에서 제공하는 메소드를 사용할 수 있습니다. Duck 클래스는 두 인터페이스를 모두 구현하므로 fly()와 swim()을 모두 사용할 수 있습니다.

이런 방식으로 Java에서 default 메소드를 사용하면 인터페이스에서 다중 상속과 유사한 기능을 제공할 수 있으며, 클래스는 필요한 인터페이스를 구현하여 다양한 기능을 효과적으로 조합할 수 있습니다.

 

Interceptor 인터페이스의 Defalut Method

 

Java 8부터 HandlerInterceptor 인터페이스에 default 메소드가 추가되었습니다. HandlerInterceptor 인터페이스는 스프링 프레임워크에서 웹 애플리케이션의 요청 처리 단계에서 실행될 수 있는 인터셉터(interceptor)를 정의하기 위한 인터페이스입니다. 이 인터페이스에 default 메소드를 추가함으로써, 이 인터페이스를 구현하는 클래스에서 필요한 메소드만 구현하고 나머지는 기본 구현을 사용할 수 있게 되었습니다.

예를 들어, HandlerInterceptor 인터페이스에는 다음과 같이 preHandle, postHandle, afterCompletion 메소드가 정의되어 있습니다:

public interface HandlerInterceptor {
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

    void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception;

    void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
            Exception ex) throws Exception;
}

 

이 중에서 필요한 메소드만 구현하고 싶을 때, Java 8 이후의 버전에서는 default 메소드를 사용하여 나머지 메소드를 구현하지 않아도 됩니다. 예를 들어, 다음과 같이 preHandle 메소드만 구현하고 나머지 메소드는 default 메소드로 제공된 기본 구현을 사용할 수 있습니다

public class MyHandlerInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // preHandle 메소드 구현
        return true;
    }
    
    // postHandle 및 afterCompletion 메소드를 구현하지 않아도 됨
}
반응형