인터페이스를 구현하는 클래스는 인터페이스에서 정의하는 모든 메서드 구현을 제공하거나 아니면 부모 클래스의 구현을 상속받아야 한다. 때문에 인터페이스를 바꾸고 싶을 때는 이전에 해당 인터페이스를 구현했던 모든 클래스도 고쳐야 한다는 문제가 발생한다.
자바 8에서는 이 문제를 해결하기 위해 기본 구현을 포함하는 인터페이스를 정의하는 두 가지 방법을 제공한다. 첫 번째는 인터페이스 내부의 정적 메서드 를 사용하는 것이고, 두 번째는 인터페이스의 기본 구현을 제공할 수 있도록 디폴트 메서드 기능을 사용하는 것이다.
API를 바꾸는 것이 왜 어려운지 예제를 통해 알아보자.
// Resizable 인터페이스의 초기 버전
public interface Resizable extends Drawable {
int getWidth();
int getHeight();
void setWidth(int width);
void setHeight(int height);
void setAbsoluteSize(int width, int height);
}
// 사용자의 구현
public class Ellipse implementes Resizable {
...
}
public class Game {
public static void main(String...args) {
List<Resizable> resizableShapes =
Arrays.asList(new Square(), new Rectangle(), new Ellipse());
Utils.paint(resizableShapes);
}
}`
// setRelativeSize 메서드를 추가한 새로운 버전의 Resizable
public interface Resizable extends Drawable {
int getWidth();
int getHeight();
void setWidth(int width);
void setHeight(int height);
void setAbsoluteSize(int width, int height);
void setRelativeSize(int wFactor, int hFactor);
}
사용자가 겪는 문제
public interface Sized {
int size();
default boolean isEmpty() { //디폴트 메서드
return size() == 0;
}
}
default void setRelativeSize(int wFactor, int hFactor) {
setAbsoluteSize(getWidth() / wFactor, getHeight() / hFactor);
}