“메모리에 대한 끔찍한”주장은 전적으로 잘못되었지만 객관적으로 “나쁜 습관”입니다. 클래스에서 상속받을 때는 관심있는 필드와 메소드 만 상속하는 것이 아니라 모든 것을 상속 합니다. 유용하지 않더라도 선언하는 모든 메소드. 그리고 가장 중요한 것은 모든 계약을 상속받으며 클래스가 제공한다는 보장입니다.
약어 SOLID는 우수한 객체 지향 디자인을위한 몇 가지 휴리스틱을 제공합니다. 여기서 I nterface 독방 원리 (ISP)와 L의 iskov 대체 Pricinple (LSP)는 말이 있습니다.
ISP는 인터페이스를 가능한 작게 유지하도록 지시합니다. 그러나에서 상속함으로써 ArrayList많은 방법을 얻을 수 있습니다. 그것은에게 의미있는 get(), remove(), set()(대체), 또는 add()특정 인덱스 (삽입) 자식 노드? ensureCapacity()기본 목록에 합당 합니까? sort()노드 란 무엇입니까 ? 클래스의 사용자는 정말 얻을되어 있습니까 subList()? 원하지 않는 메소드를 숨길 수 없으므로 유일한 해결책은 ArrayList를 멤버 변수로 사용하고 실제로 원하는 모든 메소드를 전달하는 것입니다.
private final ArrayList<Node> children = new ArrayList();
public void add(Node child) { children.add(child); }
public Iterator<Node> iterator() { return children.iterator(); }
문서에서 보는 모든 방법을 실제로 원한다면 LSP로 넘어갈 수 있습니다. LSP는 부모 클래스가 필요한 곳이면 어디든지 서브 클래스를 사용할 수 있어야한다고 말합니다. 함수가 ArrayList매개 변수로 사용하고 Node대신 전달 하면 아무것도 바뀌지 않습니다.
서브 클래스의 호환성은 형식 서명과 같은 간단한 것부터 시작합니다. 메서드를 재정의하는 경우 부모 클래스에 유효한 사용을 제외 할 수 있으므로 매개 변수 유형을 더 엄격하게 만들 수 없습니다. 그러나 그것은 컴파일러가 Java에서 우리를 확인하는 것입니다.
그러나 LSP는 훨씬 더 깊이 실행됩니다. 모든 부모 클래스와 인터페이스의 문서에서 약속 한 모든 것과의 호환성을 유지해야합니다. 에서 자신의 대답 , 린은 하나의 경우 발견했다 List(당신을 통해 상속 인터페이스 ArrayList) 보장 방법 equals()과 hashCode()방법이 일을 생각됩니다. 들어 hashCode()당신도 정확하게 구현해야합니다 특정의 알고리즘이 제공됩니다. 이것을 작성했다고 가정 해 봅시다 Node.
public class Node extends ArrayList<Node> {
public final int value;
public Node(int value, Node... children) {
this.value = Value;
for (Node child : children)
add(child);
}
...
}
이를 위해서는에 value기여할 hashCode()수없고 영향을 줄 수 없습니다 equals(). List인터페이스 - 당신이 상속에 의해 명예를 약속 - 요구 new Node(0).equals(new Node(123))사실로.
클래스에서 상속 받으면 실수로 부모 클래스가 만든 약속을 깨뜨리기가 너무 쉬워지고 일반적으로 의도 한 것보다 많은 방법을 노출하기 때문에 상속보다 구성 을 선호하는 것이 좋습니다 . 무언가를 상속해야한다면 인터페이스 만 상속하는 것이 좋습니다. 특정 클래스의 동작을 재사용하려면 인스턴스 변수에서 별도의 객체로 유지하면 모든 약속과 요구 사항이 적용되지 않습니다.
때때로, 우리의 자연어는 상속 관계를 암시합니다 : 자동차는 차량입니다. 오토바이는 차량입니다. 나는 클래스를 정의해야 Car하고 MotorcycleA로부터 그 상속을 Vehicle클래스? 객체 지향 디자인은 코드에서 실제 세계를 정확하게 반영하는 것이 아닙니다. 우리는 소스 코드에서 실제 세계의 풍부한 분류 체계를 쉽게 인코딩 할 수 없습니다.
그러한 예로는 직원-보스 모델링 문제가 있습니다. Person각각 이름과 주소를 가진 여러 개가 있습니다 . 은 Employee이다 Person하고있다 Boss. A는 Boss또한이다 Person. 따라서 및에 Person의해 상속되는 클래스를 만들어야 합니까? 이제 문제가 있습니다. 상사는 또한 직원이며 또 다른 상사입니다. 따라서 확장해야 할 것 같습니다 . 그러나이 A는 하지만은이되지 않는다 ? 어떤 종류의 상속 그래프라도 어떻게 든 분해됩니다.BossEmployeeBossEmployeeCompanyOwnerBossEmployee
OOP는 계층, 상속 및 기존 클래스의 재사용에 관한 것이 아니라 행동의 일반화 에 관한 것 입니다. OOP는“많은 객체를 가지고 있으며 특정 작업을하기를 원합니다. 그리고 어떻게 신경 쓰지 않습니까?”그것이 인터페이스 의 목적입니다. 반복 가능하도록 Iterable인터페이스를 구현하면 Node완벽하게 작동합니다. Collection자식 노드 등을 추가 / 제거하기 위해 인터페이스 를 구현하면 좋습니다 . 그러나 다른 클래스에서 상속받은 것은 위의 개요와 같이 신중하게 생각하지 않는 한 그렇지 않은 모든 것을 제공하기 때문입니다.