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();
});
}
}
public class Game {
public static void main(String...args) {
List<Resizable> resizableShapes =
Arrays.asList(new Square(), new Rectangle(), new Ellipse());
Utils.paint(resizableShapes);
}
}
- 이 상황에서 몇 개월 후에
Resizable을 구현한 Square와 Rectangle 클래스에 대해서 새로운 기능 추가 요청이 들어오게 되어
- 이 클래스들의 부모 격인
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);
}
}