devseop08 님의 블로그

[API] 람다와 스트림: Mordern Java - 13. 디폴트 메서드 본문

Language/Java

[API] 람다와 스트림: Mordern Java - 13. 디폴트 메서드

devseop08 2025. 9. 21. 15:16

13.1 변환하는 API

  • 자바 언어로 구현된 임의의 그래픽 라이브러리에 Resizable 인터페이스가 있다고 가정해보자
  • Resizable 인터페이스는 getHeight(), getWidth(), setHeight(), setWidth(),setAbsoluteSize() 메서드를 멤버로 갖고 Drawable 인퍼테이스를 상속받는다.
public interface Drawable {
    void draw();
}
public interface Resizable extends Drawable {
    int getHeight();
    int getWidth();
    void setHeight(int height);
    void setWidth(int width);
    void setAbsoluteSize(int height, int width);
}
  • 어떤 임의의 사용자가 직접 Resizable 인터페이스를 구현하는 클래스 Ellipse를 선언
public class Ellipse implements Resizable { ... }
  • 다양한 Resizable 구현체들을 처리하는 paint 메서드를 정적 멤버로 갖는 Utils 클래스
public class Utils {
    public static void paint(List<Resizable> l) {
        l.forEach(r -> {
            r.setAbsoluteSize(42, 42);
            r.draw();
        });
    }
}
  • 다양한 도형을 처리하는 Game 구현
public class Game {
    public static void main(String...args) {
        List<Resizable> resizableShapes =
            Arrays.asList(new Square(), new Rectangle(), new Ellipse());

        Utils.paint(resizableShapes);
    }
}
  • 이 상황에서 몇 개월 후에 Resizable을 구현한 SquareRectangle 클래스에 대해서 새로운 기능 추가 요청이 들어오게 되어
  • 이 클래스들의 부모 격인 Resizable 인터페이스에서 해당 기능을 나타내는 메서드를 선언함으로써
  • Resizable 인터페이스를 구현하는 모든 클래스들이 이렇게 새로 추가된 메서드를 구현하도록 한다고 해보자.
public interface Resizable extends Drawable {
    int getHeight();
    int getWidth();
    void setHeight(int height);
    void setWidth(int width);
    void setAbsoluteSize(int height, int width);
    void setRelativeSize(int hFactor, int wFactor); // 추가된 메서드
}
  • 라이브러리 설계자들과 라이브러리 사용자 모두 각자 자신이 만든 Resizable 인터페이스를 구현 클래스를 찾아 일일이 새로 추가된 setRelativeSize() 메서드를 구현해줘야만 한다.
  • 그래야만 컴파일 통과되고 setRelativeSize 메서드 호출 시점에 런타임 에러가 발생하지 않을 것이다.
  • 그런데 이런 방식은 너무 비효율적이 방법이다. 더 좋은 방법이 없을까?
  • 이러한 인터페이스에 새로운 메서드 추가 시 하위 클래스들에 대한 비효율적인 메서드 구현 문제를 해결하기 위해 디폴트 메서드라는 개념이 도입되었다.

13.2 디폴트 메서드란 무엇인가?

  • 인터페이스에 디폴트 메서드를 선언하면 이제 인터페이스는 자신을 구현하는 클래스에서 메서드를 구현하지 않아도 되는 새로운 메서드 시그니처를 제공한다.
  • 인터페이스를 구현하는 클래스에서 구현하지 않아도 되는 메서드, 즉 디폴트 메서드는 해당 인터페이스 자체에서 기본으로 구현되어 제공된다. => 그래서 디폴트 메서드라 부른다.
  • 디폴트 메서는 default라는 키워드로 시작하며 다른 클래스에 선언된 메서드처럼 메서드 바디를 포함한다.
public interface Resizable extends Drawable {
    int getHeight();
    int getWidth();
    void setHeight(int height);
    void setWidth(int width);
    void setAbsoluteSize(int height, int width);
    default void setRelativeSize(int hFactor, int wFactor){ // 추가된 메서드
        setAbsoluteSize(getHeight() / hFactor, getWidth() / wFactor);
    }
}