본문 바로가기

Reading

(65)
[Effective-Java] Item 21. 인터페이스는 구현하는 쪽을 생각해 설계하라 모든 상황에서 불변식을 해치지 않는 디폴트 메소드 작성은 어렵다. 인터페이스에 메소드를 추가하면 우연히 기존 구현체에 추가된 메소드가 상황이 아니라면 컴파일 오류가 발생한다. 원래는 기존 구현체를 깨뜨리지 않고는 인터페이스에 메소드를 추가할 방법이 없었는데, 자바8 이후에는 디폴트 메소드를 소개됐다. 디폴트 메소드를 선언하면, 재정의 하지 않았던 모든 클래스에서 디폴트 메소드가 쓰이게 된다. 자바7까지만 하더라도 현재의 인터페이스에 새로운 메소드가 추가될 일 없다라는 가정으로 작성되었으니, 디폴트 메소드는 구현 클래스에 대해 아무것도 모른 채 무작정 삽입될 뿐이다. 모든 기존 구현체들과 매끄럽게 연동되리라는 보장은 없다. 주로 람다를 활용할 목적으로 자바 8에서는 핵심 컬렉션 인터페이스에 다수의 디폴트 ..
[Effective-Java] Item 20. 추상 클래스보다는 인터페이스를 우선하라 자바가 제공하는 다중 구현 메커니즘은 인터페이스와 추상 클래스가 있다. 자바 8부터 인터페이스도 default method를 제공할 수 있어 두 메커니즘 모두 인스턴스 메소드를 구현 형태로 제공할 수 있다. 추상 클래스를 정의한 타입을 구현하는 클래스는 상속을 해야하는데, 자바가 단일 상속만 지원하니 추상 클래스 방식은 새 타입 정의에 제약이 있는 반면 인터페이스가 선언한 메소드를 모두 정의하고 규약을 잘 지킨 클래스면 어떤 클래스를 상속했든 같은 타입으로 취급된다. 인터페이스의 장점 1. 기존 클래스에도 손쉽게 새로운 인터페이스를 구현해넣을 수 있다. 인터페이스가 요구하는 메소드를 추가하고 클래스 선언에 implements 구문만 추가하면 끝이다. 반면 기존 클래스 위에 새로운 추상 클래스를 끼워넣기는..
[Effective-Java] Item 19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라. 상속을 고려한 설계와 문서화 1. 상속용 클래스는 재정의할 수 있는 메소드들을 내부적으로 어떻게 이용하는지(자기사용) 문서로 남겨야 한다. 클래스의 API로 공개된 메소드에서 클래스 자신의 또 다른 메소드를 호출할 수도 있다. ex) 아이템 18에서 AbstractCollection 클래스의 addAll 메소드가 내부적으로 add 메소드를 호출하는 것 재정의 가능 메소드(public, protected 메소드 중 final이 아닌 모든 메소드)를 호출할 수 있는 모든 상황은 문서로 남겨야 한다. (호출하는 메소드가 뭔지, 어떤 순서로 호출하는지, 호출 처리 중의 영향 등) 예를 들어, 백그라운드 스레드나 정적 초기화 과정에서도 호출이 일어날 수 있다. API 문서에서 Implementation Requi..
[Effective-Java] Item 18. 상속보다는 컴포지션을 사용하라 상속은 코드를 재사용하는 수단이지만 다른 패키지의 구체 클래스를 상속하는 일은 위험하다.(구체 클래스 상속, 인터페이스 상속과 무관) 상위, 하위 클래스 모두 같은 프로그래머가 통제하는 패키지 안이나, 확장할 목적으로 설계되었고 문서화도 잘 된 클래스는 상속도 안전하다. 상속이 문제가 발생할 때 1. 메소드 호출과 달리 상속은 캡슐화를 깨뜨린다. 즉, 상위 클래스가 어떻게 구현되냐 따라 하위 클래스 동작에 이상이 생길 수 있다. 상위 클래스가 릴리스마다 내 구현이 달라질 수 있고, 그 여파로 건드리지 않은 하위 클래스가 오동작 할 수 있다는 것이다. 상위 클래스 설계자가 확장을 충분히 고려하고 문서화도 제대로 해두지 않으면 하위 클래스는 상위 클래스 변화에 맞춰 수정해야한다. 예를들어 HashSet을 상..