# ITEM21 인터페이스는 구현하는 쪽을 생각해 설계하라

# Default Method

자바8, 기존 인터페이스에 메서드를 추가할 수 있는 방법

핵심 컬렉션 인터페이스에 디폴트 메서드가 추가 되었다.

  • 주로 람다를 활용하기 위함
  • 자바 라이브러리의 디폴트 메서드는 코드품질이 높고 범용적 → 대부분 잘 작동

# 주의 사항

# 불변식을 해치지 않는 디폴트 메서드 작성의 어려움

# 문제점

자바 8 의 Collection 인터페이스에 추가된 removeIf 디폴트 메서드

default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);
    boolean result = false;
    for (Iterator<E> it = iterator(); it.hasNext(); ) {
        if (filter.test(it.next())) {
            it.remove();
            result = true;
        } 
    }
    return result;
}
1
2
3
4
5
6
7
8
9
10
11

apache.commons.collections4.collection.SynchronizedCollection

  • 클라이언트가 제공한 객체로 락을 거는 능력을 추가로 제공
  • 모든 메서드에서 주어진 락 객체로 동기화 한 후 내부 컬렉션 객체에 위임하는 래퍼클래스
  • removeIf 와 맞지 않음 (effective java 3판 작성시점)
    • removeIf 의 구현은 동기화에 대해 모르므로 락 객체를 사용할 수 없다.

# 해결 방안

  • 구현한 인터페이스의 디폴트 메서드 재정의

자바 플랫폼에 속하지 않은 제 3의 기존 컬렉션 구현체에서는 여전히 수정되지 않고 있을 수 있다.



# 디폴트 메서드는 컴파일에 성공하더라도 기존 구현체에 런타임 오류를 일으킬 수 있다.

흔한일은 아니지만 일어날 수 있다.

# 기존 인터페이스에 디폴트 메서드로 새 메서드를 추가하는 일은 꼭 필요한 경우가 아니면 피한다.

디폴트 메서드가 기존 구현체들과 충돌하지 않는지 고려한다.

새로운 인터페이스를 만드는 경우라면 유용한 수단이다.

# 디폴트 메서드는 인터페이스로부터 메서드를 제거하거나 기존 메서드의 시그니처를 수정하는 용도가 아니다.

이런 형태로 인터페이스를 변경하면 기존 클라이언트를 망가뜨리게 된다.

# 새로운 인터페이스라면 릴리스 전에 반드시 테스트를 거쳐야 한다.

인터페이스를 릴리즈 한 후의 결함 수정 가능성에 대해 기대서는 안된다.