-
이펙티브 자바 - Item 21 - 인터페이스는 구현하는 쪽을 고려해서 설계하라언어/Effective Java 2024. 6. 4. 09:20
인터페이스에 메서드 추가
- 자바 8 전에는 기존 구현체를 깨뜨리지 않고 인터페이스에 메서드를 추가할 방법은 존재하지 않았다. 자바 8부터 디폴트 메서드를 통해서 기존 인터페이스에 메서드를 추가할 수 있게 되었다.
- 디폴트 메서드를 선언하면, 그 인터페이스를 구현한 후 디폴트 메서드를 재정의하지 않은 모든 클래스에서 디폴트 구현이 쓰이게 된다.
- 단, 이렇게 디폴트 메서드를 추가한다고해도 기존 구현체들과 매끄럽게 연동된다는 보장은 없다.
생각할 수 있는 모든 상황에서 불변식을 해치지 않는 디폴트 메서드를 작성하기란 어렵기 때문이다.
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; }
- 이 코드는 범용적으로 작성되었지만, 현존하는 모든 Collection 구현체와 잘 어우러지는 것은 아니다.
- 대표적인 예가 SyncronizedCollection다.
- 아파치 커먼즈 라이브러리의 클래스는 클라이언트가 제공한 객체로 락을 거는 능력을 추가로 제공한다.
- 즉 모든 메서드에서 주어진 락 객체로 동기화한 후 내부 컬렉션 객체에 기능을 위임하는 래퍼 클래스다.
- 현재는 SynchronizedCollection 클래스가 removeIf메서드를 재정의하고 있지 않고 있다. removeIf 메서드는 동기화에 관해 아무것도 알지 못하므로 락 객체를 사용할 수가 없다.
디폴트 메서드는 오류를 일으킬 가능성이 있다.
- 디폴트 메서드는 컴파일에 성공하더라도 기존 구현체에 런타임 오류를 일으킬 수 있다.
- 따라서 기존 인터페이스에 디폴트 메서드로 새 메서드를 추가하는 일은 피하자
- 반면, 새로운 인터페이스를 만드는 경우라면, 표준적인 메서드 구현을 제공하는데 아주 유용한 수단이다.
인터페이스 설계 시 주의가 필요하다.
- 디폴트 메서드라는 도구가 생겼지만 인터페이스 설계할 떄는 여전히 주의를 기울일 필요가 있다.
- 어떤 위험이 딸려올지 알 수 없기 때문이다!
인터페이스 릴리즈 전에 테스트를 거치자
- 새로운 인터페이스라면, 릴리스 전에 반드시 테스트를 거쳐야 한다.
- 서로 다른 방법으로 최소 세가지 구현, 혹은 다양한 클라이언트를 만나보자
'언어 > Effective Java' 카테고리의 다른 글
이펙티브 자바 Item 25 - 톱레벨 클래스는 한파일에 하나만 담자 (0) 2024.06.04 이펙티브 자바 Item 24 - 멤버 클래스는 되도록 static으로 만들라 (1) 2024.06.04 이펙티브 자바 Item 20 - 추상클래스보다는 인터페이스를 우선시하라 (0) 2024.05.31 이펙티브 자바 Item 18 - 상속보다는 컴포지션을 사용하라 (1) 2024.05.31 이펙티브 자바 Item 17 - 변경 가능성을 최소화하라 (0) 2024.05.30