자바8 디폴트메소드
자바 인터페이스는 약속이다. 클래스가 할 수 있는 것을 정의한 게 인터페이스다. 따라서 모든 객체지향개념에서 말하는 공통된 기조는 모든 의존은 인터페이스로 향하라고 한다. 왜냐면 인터페이스는 약속이라서 바뀌지 않을거니까.. 우리 부동산 계약서 같은 거니까..
하지만 세상에 바뀌지 않는 건 모든게 바뀐다는 사실이다. 인터페이스 만들 때 머리 싸매고 잘 만들었다고 해도 언젠가 바뀐다. 결국 바뀐다. 근데 인터페이스는 바뀌면 안된다. API 만들어서 배포했는데 그 후에 인터페이스 바꿔서 배포하면 사용자는 바뀐 라이브러리 jar 파일이 바뀌자마자 그 인터페이스 implements 한 class 파일에 빨간색 뜨고 난리난다. 이거 어떻게 하나.. 머리 아프다...
기존에는 뭐뭐뭐V2 이런식으로 인터페이스 만들고 앞으로 이거 쓰세요 했다.. 그래서 한동안은 V1과 V2를 같이 관리하고 api에 deprecated 붙여서 금방 없어질 것처럼 협박한다.. 그래도 못 없앤다... 없애면 잘 쓰던 사람들 난리나니까.. 울며 겨자먹기로 계속 두개 다 관리하면서 지내야한다.
그래서 자바8에서 디폴트 메소드라는 개념이 새로 나왔다. 이거 쓰면 위에 있는 문제들 싹 해결된다.
쓰는 방법은 매우 간단하다. 인터페이스안에 메소드 선언 시 default 키워드만 붙여주면 된다.
아래 예제 소스를 보자
원래 Person 인터페이스는 getName()이라는 메소드만 있었다. 그런데 이후 printName이라는 메소드가 추가로 필요하게 됐다면 위 소스처럼 붙여주면 된다. 그러면 기존에 Person을 implements하던 class들은 전혀 문제가 없고 새롭게 Person을 implements하는 class들도 printName() 메소드를 사용할 수 있게 된다.
자바8 API에서는 이미 디폴트 메소드를 사용해서 API를 만들었다. 대표적으로 List 인터페이스에 sort()메소드를 디폴트 메소드로 추가했다.
따라서 List<Person> people이 있다고 치면
기존에는 Collections.sort(people, comparator) 로 했다면
people.sort(comparator) 이런식으로 작성이 가능하게 됐다.
아래는 실제 자바 8 의 sort 메소드 소스이다. 참고하시라.
@SuppressWarnings({"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
그리고 앞으로 포스팅 하겠지만 람다를 사용하게 되면 위의 comparator 메소드 부분에 익명클래스 대신 람다를 써서 좀 더 깔끔하게 사용할 수 있게 되었다.