자바 8 이전에는 기존 구현체를 깨뜨리지 않고는 인터페이스에 메소드를 추가 할 방법이 없었다.

인터페이스에 메소드를 추가하면 구현체에 컴파일오류가 난다.

 

자바 8에 들어와서는 메소드를 추가할 수 있게끔 디폴트 메소드가 나왔는데 여전히 위험은 남아있다.

 

디폴트 메소드를 선언하면, 그 인터페이스를 구현한 후 디폴트 메소드를 재정의하지 않은 모든 클래스에서 디폴트 구현이 쓰이게 된다.

(약간 추상클래스에서 처럼 가져다쓰는거랑 비슷한 개념인듯?)

 

그러나 자바 7까지는 기존 인터페이스에 새로운 메소드가 추가될 일은 없다고 확신한채로 개발했기 때문에 매끄럽게 연동되지 않는다.

 

자바 8에서는 람다를 활용하기 위해 핵심 컬렉션 인터페이스들에 다수의 디폴트 메소드가 추가되었다.

 

Collection 인터페이스에 추가된removeIf 메소드를 예로 보겠다.

 

 

타입이 deafult로 지정되어있다.

이 메소드는 주어진 boolean 함수(predicate)가 true를 반환하는 모든 원소를 제거한다.

 

디폴트 구현은 반복자를 이용해 순회하면서 각 원소를 인수로 넣어 predicate를 호출하고

predicate가 ture를 반환하면 반복자의 remove메소드를 호출해 그 원소를 제거한다.

 

이 deafult 메소드는 SynchronizedCollection 클래스와 잘 어울리지 않는데, 그 이유는 다음과 같다.

이 클래스는 클라이언트가 제공한 객체로 락을 거는 능력을 추가로 제공한다.

즉, 모든 메소드에서 주어진 락 객체로 동기화한 후 내부 컬렉션 객체에 기능을 위임하는 래퍼 클래스이다.

 

설명에서도 Wrapper라고 명시되어있다.

 

책에서는 SynchronizedColletion은 removeIf를 재정의하고 있지 않기 때문에 동기화 문제가 발생한다고 했는데

자바 11버전에서 확인해보니 removeIf를 재정의하고 있다.

재정의시에 mutex를 통해 동기화를 해주는 것을 확인할 수 있다.

이전 버전에서는 이렇지 않았나보다!

 

아무튼 이런식으로 default 메소드를 만들고 재정의가 필요한 곳에서 재정의가 이루어지지 않으면 여러가지 문제를

발생시킬 수 있다는 것이 이번 챕터의 요지다.

 

정리 - 디폴트메소드로 새 메소드를 추가하는 일은 꼭 필요한 경우가 아니면 피해야 한다.

+ Recent posts