50

이 질문에는 이미 답변이 있습니다.

상속에 대한 컴포지션 우선 순위 지정

매우 인기있는 문구입니다. 나는 몇몇 기사를 읽고 각 기사는 끝에 말한다

클래스 사이에 순수한 IS-A 관계가있을 때 상속을 사용하십시오.

의 예이 기사:

여기에사과과일명확한 IS-A 관계, 즉 Apple IS-A Fruit이 있지만, 저작자는 상속을 통해 구현 될 때 함정을 표시하는 Apple HAS-A Fruit (구성)으로 표시했습니다.

나는 여기서 다소 혼란스러워졌다. 성명서의 의미는 무엇인가?

클래스 사이에 순수한 IS-A 관계가있을 때 상속을 사용하십시오.

상속에 비해 컴포지션을 사용한다는 것은 항상시험작곡을 적용하다설사순수한 IS-A 관계가 있고 상속을 떠난다.구성이 이해가 안되는 경우에만?


  • 왜 자바 레이블? - TT_

7 답변


68

상속을 사용하여 메소드를 재정의하고 다른 다형성 비헤이비어를 정의하는 대신 슈퍼 클래스의 코드를 재사용 할 때 상속 대신 컴포지션을 사용해야한다는 표시가됩니다.

그만큼java.util.Properties클래스는 상속의 나쁜 사용의 좋은 예입니다. 오히려~을 사용하여그 property를 포함하는 Hashtable확장하다메소드를 재사용하고 위임을 사용하여 메소드 일부를 다시 구현하는 것을 피하기 위해 Hashtable.


  • 나는 자동차, 동물 또는 과일을 포함하지 않는 실제 사례를 인용 한 이후로 반대표를 던졌다. 그러나, 어떻게하면 그java.util.Properties확장HashTable그 결과 디자인에 부정적인 영향을 미쳤습니다. Liskov Substitution Principle에 대해 생각해 보았지만 문제라고 생각하지 않습니다. 이론적으로는 성능 / 메모리 이유로 인해 저장 (해싱) 메커니즘을 변경할 수 있지만 상속으로는 불가능하며 구성이 가능할 수 있습니다. - Fuhrmanator
  • non-rethorical 질문 : 모든 하위 클래스에 대해 완벽하게 이해하는 메서드를 포함하는 기본 클래스를 작성하는 것은 바람직하지 않습니다. 기본 클래스를 재정의하지 마십시오. 방법? the is notProperties확장Hashtable사례 단지 상속의 나쁜 사용의 좋은 예입니다.Properties전체를 신경 쓰지 말아야한다.Hashtable특정 로직과 그것의 작은 하위 세트 만 필요하므로 확장되어서는 안됩니다Hashtable, 그것 때문에~이다.하나도 아니야.용도하나? - SantiBailors

5

나는 이것이 객체 지향 디자인에서 가장 논의 된 부분 중 하나라고 생각한다. 이 기사에서 제안한 것처럼 구성은 상속보다 항상 선호됩니다. 그렇다고 상속을 절대로 사용해서는 안된다는 의미는 아닙니다. 당신은 그것이 더 이해하기 쉬운 곳이어야합니다 (그것은 논쟁의 여지가 있습니다).

컴포지션을 사용하면 여러 가지 장점이 있습니다. 그 중 몇 가지는 다음과 같습니다.

  • 구현을 완전히 제어 할 수 있습니다. 즉, 공개하려는 메소드 만 노출 할 수 있습니다.
  • 수퍼 클래스의 모든 변경 사항은 클래스에서 수정하면 보호 될 수 있습니다. 클래스를 사용하는 모든 클라이언트 클래스는 수정할 필요가 없습니다.
  • 수퍼 클래스로드 (지연로드)를 제어 할 수 있습니다.


  • 내 문제는 더 많은 조합으로 옮겨가는 것이 아니라 많은 방법을 가진 클래스의 경우 모든 파생 된 클래스에서 반복되는 반복을 반복하는 것이 어려울 수 있다는 것입니다. 물론 대부분의 클래스에는 몇 가지 메소드가 있어야하지만 경우에 따라 (예 : GUI Window 기본 클래스) 많은 도움을 줄 수는 없습니다. - LegendLength

3

이 기사에는 그러한 문구가 없습니다.

use inheritance when there is pure IS-A relationship between classes

또한 Google은 귀하의 게시물을 제외한 다른 곳에서 Google을 찾지 않았습니다.

대신이 기사는 다음과 같이 표시됩니다.

Make sure inheritance models the is-a relationship. My main guiding philosophy is that inheritance should be used only when a subclass is-a superclass. In the example above, an Apple likely is-a Fruit, so I would be inclined to use inheritance.

즉, IS_A 관계가있는 경우 상속을 먼저 사용하고 합성을 시도하지 마십시오. 그리고 선호도가 없습니다.using composition over inheritance- 각각은 자신의 역할에 도움이됩니다.


  • each is good for its own role.+1. 나는 이것이 "우리의 동기"에 달려 있음을 의미한다고 생각합니다. 이를 위해 우리는 우리 반 사이의 관계를 수립하고 있습니다. "ONLY"인 경우, 코드 재사용을 위해Favor composition over inheritance가 유효하고 "그 동기가"실제 관계 "를 모델링하는 것이라면, 실제로 클래스들 사이에 존재하기 때문에 상속과 구성 모두 자신의 역할을합니다. 순수 IS-A 관계가 "있음에도 불구하고"존재한다면 상속을 선택할 수있다. 상속은 강한 결합과 같은 구성보다 더 많은 문제가 있다는 사실, 그렇지 않으면 구성을 선택합니다. 내가 맞습니까? - a Learner
  • 코드 재사용은 강력한 동기이며, 이것만으로도 상속을 선택할 수 있습니다. 강한 커플 링은 많은 경우 문제가 아닌 유리한 것으로 간주 될 수 있습니다. 그리고 많은 언어 (자바)에서는 상속이 구성보다 쉽습니다. 오직 경험 만이 주어진 사건에 대한 올바른 접근 방식에 대한 느낌을 줄 수 있으며 엄격한 규칙은 없습니다. - Alexei Kaigorodov

3

또한, 나는 그것을 추가하고 싶다.장식 패턴는 composition over inheritance를 사용하고 객체에 대한 책임을 동적으로 추가 할 수있는 예제입니다. Decorator 패턴의 예제는 "Inheritance Over Composition Composition"항목에서 Effective Java에 언급되어 있습니다. Java API에서 예제를 얻으려면; BufferedReader는 Reader (FileReader, PipedReader, FilterReader 등을 확장하는 대신)를 장식하므로 모든 종류의 Reader를 꾸밀 수 있습니다. 버퍼링 기능은 런타임에 이러한 판독기에 부착되며 Decorator 패턴입니다.

여기서 서브 클래 싱을 통한 확장은 비실용적입니다.


3

나는 좋은 지침이 될 것이라고 생각한다.

IS-A 관계가있을 때, 상속을 사용하십시오. 그렇지 않으면   구성.

그 이유는 객체 지향 디자인 (polymorphism)이라는 또 다른 개념과 관련이 있기 때문입니다. 다형성 (Polymorphism)은 다른 객체 대신에 객체를 사용할 수있는 많은 OOP 언어의 특징입니다. 단, 첫 번째 객체의 클래스는 두 번째 객체의 하위 클래스입니다.

설명하기 위해 동물의 유형을 취하는 함수가 있는지 상상해보십시오. 상속을 사용하면 하나의 함수 만 사용할 수 있습니다.

void feed( Animal a );

다형성 (Polymorphism)은 동물의 하위 클래스가 받아 들여질 것이라는 확신을줍니다. 그렇지 않으면 각 유형에 대해 하나의 함수를 작성해야합니다. 이 장점은 단점 (예 : 축소 된 캡슐화)을 능가한다고 생각합니다.

IS-A 관계가 없다면 다형성이 그리 효과적이지 않을 것이라고 생각합니다. 따라서 컴포지션을 사용하고 클래스간에 캡슐화 / 격리를 강화하는 것이 좋습니다.


  • If there is no IS-A relationship, I think polymorphism won't be very effective. It would thus be better to use composition and have enhanced encapsulation/isolation between classes.+1 - a Learner

2

관계가 영구적 일 때 상속을 사용하십시오. 자유로운 행동을하기 위해 확장 기능을 사용하지 마십시오. 이것이 IS-A 예제에서 언급 한 것입니다. 확장 클래스가 진정으로 부모의 확장 인 경우에만 확장하십시오. 그것이 잘리고 건조하지 않은 때가있을 것입니다, 그러나 일반적으로. 작문은 "올바른"수업에서 연장해야하는 경우에도 미래에도 유연성을 제공합니다.

이것은 오래되었지만 훌륭한 기사입니다.

http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html


0

나는 안된다고. 과일 / 사과 시나리오에서는 상속을 사용하는 것이 좋습니다. 이 기사의 저자는 "위의 예에서 Apple은 과일 일 가능성이 높습니다. 따라서 상속을 사용하려고합니다."라고 확인했습니다.

하위 클래스가 분명히 수퍼 클래스이면 상속이 좋습니다. 실제로는 작곡을 사용하면 더 많은 상황을 해결할 수 있습니다.


  • " 하위 클래스가 분명히 수퍼 클래스 인 경우 " ? - Simon Nickerson
  • @SimonNickerson "If<what-your-subclass-models>명확하게 IS-A<what-your-superclass-models>" - Joffrey

연결된 질문


관련된 질문

최근 질문