이것은 발굴을 시작할 때까지 "분명히 좋은 생각"으로 보이는 언어 디자인 문제 중 하나이며 실제로는 그것이 나쁜 생각임을 깨닫게됩니다.
이 메일 에는 주제 (및 기타 주제)에 많은 내용이 있습니다. 현재 디자인으로 우리를 데려 오기 위해 수렴 된 여러 디자인 세력이있었습니다.
- 상속 모델을 단순하게 유지하려는 욕구;
- 일단 당신이 명백한 예를 지나친다는 사실 (예 :
AbstractList
인터페이스로 equals / hashCode / toString 상속은 단일 상속 및 상태와 밀접한 관련이 있으며 인터페이스는 여러 번 상속되고 상태 비 저장됨을 알 수 있습니다.
- 그것은 잠재적으로 놀라운 행동의 문을 열었습니다.
당신은 이미 "간단하게 유지"목표를 다뤘습니다. 상속 및 충돌 해결 규칙은 매우 단순하도록 설계되었습니다 (클래스가 인터페이스를 통해, 파생 된 인터페이스가 슈퍼 인터페이스를 통해, 다른 모든 충돌이 구현 클래스에 의해 해결됨). 물론 이러한 규칙은 예외를 만들기 위해 조정될 수 있습니다. 나는 당신이 그 줄을 당기기 시작할 때, 증가하는 복잡도는 생각만큼 작지 않다는 것을 알게 될 것입니다.
물론, 더 많은 복잡성을 정당화 할 수있는 어느 정도의 이점이 있지만이 경우에는 그렇지 않습니다. 여기서 말하는 방법은 equals, hashCode 및 toString입니다. 이러한 방법은 모두 본질적으로 객체 상태에 관한 것이며 인터페이스가 아닌 상태를 소유하는 클래스입니다. 인터페이스가 아니라 해당 클래스에 대한 평등의 의미를 결정하는 가장 좋은 위치에 있습니다 (특히 평등에 대한 계약이 매우 강력하기 때문에 효과적인 참조). 놀라운 결과를위한 자바); 인터페이스 작성자가 너무 멀리 제거되었습니다.
AbstractList
예제를 꺼내는 것은 쉽습니다 . 인터페이스 AbstractList
를 제거 하고 동작을 제거 할 수 있다면 좋을 것 List
입니다. 그러나이 명백한 예를 넘어 서면 찾을 수있는 다른 좋은 예는 많지 않습니다. 기본적 AbstractList
으로 단일 상속을 위해 설계되었습니다. 그러나 인터페이스는 다중 상속을 위해 설계되어야합니다.
또한이 클래스를 작성한다고 상상해보십시오.
class Foo implements com.libraryA.Bar, com.libraryB.Moo {
// Implementation of Foo, that does NOT override equals
}
Foo
퍼 유형의 작가 외모, 등호의 어떤 구현을 볼 수 없습니다, 그리고 얻을 참조 평등을 마무리, 그가 할 필요가 모두 상속 동등하다 Object
. 그런 다음 다음 주에 Bar의 라이브러리 관리자가 "유용하게"기본 equals
구현을 추가합니다 . 죄송합니다! 이제 Foo
다른 유지 관리 도메인의 인터페이스에 의해 의미론 이 깨져서 일반적인 방법에 대한 기본값을 "유용하게"추가했습니다.
기본값은 기본값입니다. 계층 구조의 아무 곳에 나없는 인터페이스에 기본값을 추가하면 구체적인 구현 클래스의 의미에 영향을 미치지 않아야합니다. 그러나 기본값이 Object 메소드를 "재정의"할 수 있다면 사실이 아닙니다.
따라서 무해한 기능처럼 보이지만 실제로는 매우 해 롭습니다. 점진적 표현력이 적기 때문에 많은 복잡성이 추가되며 별도로 컴파일 된 인터페이스를 손상시키기 위해 의도가 좋고 무해한 모양의 변경이 너무 쉽습니다. 클래스 구현의 의미론.