-
Notifications
You must be signed in to change notification settings - Fork 0
Description
자바 8 이전
자바 8 이전에는 기존 구현체를 꺠뜨리지 않고는 인터페이스에 메서드를 추가할 수 있는 방법이 없었다. ( 인터페이스에 메서드 추가 시 컴파일 오류가 나는데 이는 만약 오픈 소스코드를 만들었는데 새로운 메소드를 만들어야 할 때가 생길 수 있다. 이때 내가 잘못만든 코드로 인해 모든 사람에게 오류가 발생하는 심각한 사태가 발생할 수 있다. )
자바 8 이후
interface NewInterface {
default void newFuntion() {
System.out.println("new Function");
}
}
Defaul 메소드의 등장
자바 8에 와서 기존 인터페이스에 새로운 메소드를 추가할 수 있도록 default 메소드가 생겼다. 하지만 그렇다해도 위험이 완전히 사라진 것은 아니다.
자바 7까지는 세상에서는 모든 클래스가 현재의 인터페이스에 새로운 메서드가 추가될 일은 영원히 없다. 라고 가정 후 작성되었던 코드였다. 이후 등장한 default 메소드는 이를 무시한 채 무작정 삽입될 뿐이다. 따라서 불변식을 해치지 않는 default 메소드 생성은 어려운 법이다.
예
default boolean removeIf(Predicate<? super E> filter) {
Object.requireNonNull(filter);
boolean result = false;
for (Iterator<E> it = iterator(); it.hasNext(); ) {
if (filter.test(it.next())) {
it.remove();
result = true;
}
}
return result;
}
다음은 자바 8에 추가된 removeIf 메서드이다. 이 코드보다 더 범용적으로 구현하기도 어렵겠지만, 그렇다고 해서 현존하는 모든 Collection 구현체와 어울리는 것도 아니다. 아파치의 SynchronizedCollection에서 removeIf를 사용하게 된다면 여러 스레드가 공유하는 환경에서 동기화를 제공해주지 못한다. 이는 예기치 못한 결과로 이어질 수 있다.
이를 막기 위한 자바 플랫폼의 조치
구현한 인터페이스의 디폴트 메서드를 재정의하고, 다른 메서드에서 디폴트 메서드를 호출하기 전에 사전 작업을 수행하게 했다. 위의 예로는 SynchronizedCollection이 반환하는 package-private 클래스들은 removeIf를 재정의하고, 이를 호출하는 다른 메서드들은 디폴트 메서드 호출 이전에 동기화 하도록 했다.
하지만 디폴트 메서드는 기존 구현체에 런타임 오류를 일으킬 수 있다. 따라서 기존 인터페이스에 디폴트 메서드로 새 메서드를 추가하는 일은 가능한 피해야한다.
핵심
default 메서드가 생겼다 해도 인터페이스 설계할 때는 세심한 주의를 기울여야한다. 항상 자바에서 주장하는 불변을 생각하며 신중하게 설계하도록 하자.
인터페이스를 릴리즈 한 ㅎ라도 결함을 수정하는 게 가능하지만, 그 가능성에 기대서는 안 된다.