Java에서 상속을 금지해야하는 이유는 무엇입니까 (예 : 단일 개인용 매개 변수없는 생성자를 사용하는 최종 클래스 또는 클래스 사용)? 방법을 최종적으로 만드는 좋은 이유는 무엇입니까?
Java에서 상속을 금지해야하는 이유는 무엇입니까 (예 : 단일 개인용 매개 변수없는 생성자를 사용하는 최종 클래스 또는 클래스 사용)? 방법을 최종적으로 만드는 좋은 이유는 무엇입니까?
답변:
여기에서 가장 잘 언급 할 것은 Joshua Bloch의 훌륭한 책 "Effective Java"의 항목 19이며, "상속을위한 디자인 및 문서 또는 금지"입니다. (제 2 판의 17 번 항목과 제 1 판의 15 번 항목입니다.) 실제로 읽어야하지만 요약하겠습니다.
상속 된 클래스와 부모와의 상호 작용은 조상이 상속되도록 설계되지 않은 경우 놀랍고 실행 불가능합니다.
그러므로 수업은 두 종류로 이루어져야합니다.
확장 되도록 고안된 클래스 및 수행 방법을 설명하기위한 충분한 문서
최종으로 표시된 수업
순전히 내부 코드를 작성하는 경우 약간 과잉 일 수 있습니다. 그러나 클래스 파일에 5자를 추가하는 데 드는 추가 노력은 매우 적습니다. 내부 소비에 대해서만 작성하는 경우 미래 코더는 항상 '최종'을 제거 할 수 있습니다. "이 클래스는 상속을 염두에두고 설계되지 않았다"는 경고로 생각할 수 있습니다.
클래스를 재정의하면 다른 메서드에서 계산되는 동작을 변경할 수 없도록 메서드를 최종적으로 만들 수 있습니다. 생성자에서 호출 된 메소드는 종종 final로 선언되므로 객체를 만들 때 불쾌한 놀라움을 느끼지 않습니다.
final
.
최종 방법으로 갈 수있는 3 가지 사용 사례가 있습니다.
수업을 마무리하기위한 목적 :
어떤 신체도 그러한 클래스를 확장하고 그들의 행동을 바꿀 수 없습니다.
예 : 래퍼 클래스 정수는 최종 클래스입니다. 해당 클래스가 최종 클래스가 아닌 경우 어느 누구도 Integer를 자신의 클래스로 확장하고 정수 클래스의 기본 동작을 변경할 수 있습니다. 이를 피하기 위해 java는 모든 래퍼 클래스를 최종 클래스로 만들었습니다.
DerivedInteger
되었다고 가정하면 여전히 원래 Integer 클래스를 변경하지 않으며 사용하는 사람은 DerivedInteger
스스로 위험을 감수해야하므로 여전히 왜 문제인지 알 수 없습니다.
불변의 객체 ( http://en.wikipedia.org/wiki/Immutable_object )를 만들거나 싱글 톤 ( http://en.wikipedia.org/wiki/Singleton_pattern ) 을 만들 거나 원하는 경우 효율성, 안전 또는 보안상의 이유로 누군가가 메소드를 대체하지 못하도록합니다.
상속은 전기 톱과 같습니다-매우 강력하지만 잘못된 손에는 끔찍합니다. 상속 할 클래스를 설계하거나 (유연성을 제한하고 더 오래 걸릴 수 있음) 금지해야합니다.
Effective Java 2nd edition items 16 and 17 또는 내 블로그 게시물 "Inheritance Tax"를 참조하십시오 .
흠 ... 두 가지를 생각할 수 있습니다.
특정 보안 문제를 다루는 클래스가있을 수 있습니다. 공격자는이를 하위 분류하고 시스템의 하위 분류 버전을 시스템에 공급함으로써 보안 제한을 우회 할 수 있습니다. 예를 들어 응용 프로그램에서 플러그인을 지원할 수 있으며, 플러그인이 보안 관련 클래스를 서브 클래 싱 할 수있는 경우이 트릭을 사용하여 서브 클래스 버전의 플러그인을 제자리에 밀입시킬 수 있습니다. 그러나 이것은 애플릿 등과 관련하여 Sun이 처리해야하는 문제 일 수 있습니다.
훨씬 더 현실적인 것은 객체가 변경 가능한 것을 피하는 것입니다. 예를 들어 문자열은 변경할 수 없으므로 코드에서 안전하게 참조를 유지할 수 있습니다
String blah = someOtherString;
먼저 문자열을 복사하는 대신. 그러나 문자열을 서브 클래 싱 할 수있는 경우 문자열 값을 수정할 수있는 메소드를 추가 할 수 있습니다. 이제는 위와 같이 문자열을 복사하면 문자열이 동일하게 유지되는 코드를 더 이상 신뢰할 수 없습니다. 끈.
클래스와 메서드를 final로 표시하면 런타임에서 지정된 개체를 호출하기 위해 올바른 클래스 메서드를 찾을 필요가 없으므로 성능이 약간 향상 될 수 있습니다. 비 최종 메소드는 가상으로 표시되어 필요한 경우 적절하게 확장 할 수 있으며 최종 메소드는 클래스에서 인라인으로 직접 링크하거나 컴파일 할 수 있습니다.
사람들이 자신과 다른 사람을 혼란스럽게 할 수있는 일을하지 못하게합니다. 상수 또는 계산이 정의 된 물리 라이브러리를 상상해보십시오. 최종 키워드를 사용하지 않으면 누군가가 와서 절대로 변경해서는 안되는 기본 계산이나 상수를 재정의 할 수 있습니다.