본 서적에서는 reification을 실체화 로 표현했으나 이것은 realization 이랑 헷갈리고 개인적으로 판단할 시 개념과도 맞지 않아서 구체화 로 표현함
2. 배열은 구체화(reification) 자료형
배열의 자료형은 실행시간에 결정된다. 하지만 List는 안됨
example
String strs = new String[] {"str1", "str2"}
구체화 불가능 자료형(non-refiable types)
실행시점(runtime)에 해당 자료형의 모든 정보를 이용할 수 없는 자료형(a type this is not completely available at runtime)이라는 뜻이라는데 명확하게 이해가 안되었으나, 이제는 이해가 되는 거 같다.
선지식으로 Java가 Generic을 구현할 시 내부적으로 타입제거(Type erasure) 를 이용하는 것이다. List<String>의 경우 컴파일 시에는 List<String> 이지만 런타임 시에는 List가 된다.
즉. 런타임 시에는 Parameterized type 정보인 <String>가 없어지는 타입제거(Type erasure)가 된 후이기 때문에 해당 제네릭 정보를 알 수 없고 이것이 바로 타입의 모든 정보를 런타임 시에 알 수 없는 것이다.
E, List<E>, List<String>와 같은 자료형은 구체화 불가능(non-refiable) 자료형으로 알려져 있다. - 반대로 primitive, non-generic 타입, raw 타입, 비한정 와일드카드형 타입(<?>)은 구체화 가능(refiable) 자료형이다.
변경 가능한 클래스로 만들 타당한 이유가 없다면, 반드시 변경 불가능 클래스로 만들어야 한다.
변경 불가능한 클래스로 만들 수 없다면, 변경 가능성을 최대한 제한하라.
특별한 이유가 없다면 모든 필드는 final로 선언하라.
초기화 메서드(재초기화포함)를 제공하지 마라.
Rule 16 - 계승(상속)하는 대신 구성하라 (중요)
계승은 캡슐화 원칙을 위반한다.
상위클래스에 의존적이기 때문에 만약 상위클래스가 변화하면 하위클래스가 망가질 수 있다.
상위클래스의 하위클래스가 강결합 상태이고, 즉 상위 클래스가 캡슐화가 되지 않는 다는 것
간단한 해결방법 (구성)
계승하지 않고 객체에 private 필드 하나를 두는 것
example 포장클래스를 통한 구성
계승은 하위 클래스가 상위 클래스의 하위 자료형(subtype)이 확실한 경우에만 바람직하다
즉 IS-A 관계가 성립할 때만 계승해야한다.
IS-A 의 관계는 클래스와 객체의 관계이고 IS KIND OF가 더 적절한 거 같다.
계승을 사용한 안좋은 예
Properties와 HashMap : Properties#getProperty와 HashMap#get 이 상호 접근을 허용한다.
결론
가능하면 계승 을 하지 않고 구성 을 사용하자. 포장 클래스 구현에 인터페이스가 있다면 더욱 그렇다.
Rule 17 - 계승을 위한 설계와 문서를 갖추거나, 그럴 수 없다면 계승을 금지하라
규칙 세부사항
재정의 가능 메서드를 내부적으로 어떻게 사용하는지(self-use) 반드시 문서에 남기라는 것이다.
재정의 가능 메서드 : public, protected의 일반(non final)메서드
어떤 메서드가 어떤 다른 메서드나 클래스에 의존하고 있고, 어떻게 작동되는지 상세하게 서술한다.
클래스 내부 동작에 개입할 수 있는 훅(hooks)을 신중하게 고른 protected 메서드 형태로 제공해야한다.
계승을 위해 설계한 클래스를 테스트할 유일한 방법은 하위클래스를 직접 만들어 보는 것이다.
적절하게 테스트케이스를 만들어서 다양한 케이스로 테스트를 해보는 것 뿐이다. : 3개는 만들어보자.
생성자 는 직접적이건 간접적이건 재정의 가능 메서드를 호출해서는 안된다는 것이다.
example
Cloneable나 Serializable와 같은 인터페이스를 구현한다면 계승을 사용하지 않는 것이 낫다.
너무 과도한 책임이 졔약이 생긴다.
결론
계승을 위한 클래스를 설계하면 클래스에 상당한 제약이 가해진다.계승에 맞도록 철저하게 설계하고, 문서화하지 않은 클래스에 대한 하위클래스를 만들지 않는 것이다.final 로 클래스를 만들던지, public 생성자를 제공하지 않으면 된다.
계승을 할 수없게 막았다면 구성을 통해 확장하면 된다.
계승을 위한 안전한 구현
클래스 내부적으로 재정의 가능 메서드를 사용하는 경우(self-use)를 완전히 제거하는 방법
재정의 가능 메서드의 내부 코드를 private로 선언된 도움 메서드 안으로 옮긴다.
각각의 재정의 가능 메서드가 해당 메서드를 호출하게 한다.
재정의 가능 메서드를 호출하는 내부 코드는 전부 해당 private 도움 메서드 호출로 바꾼다.