programing

상속과 구성의 차이

prostudy 2022. 4. 27. 21:34
반응형

상속과 구성의 차이

구성과 상속은 동일한가?구성 패턴을 구현하려면 자바에서 어떻게 해야 할까?

그들은 완전히 다르다.상속은 "is-a" 관계다.작문은 "has-a"이다.

다른 클래스의 인스턴스를 사용하여 작문을 수행하는 경우C학급의 영역으로 확장하는 대신C 좋았을.java.util.Stack 현재장장을 하고 있다.java.util.Vector이것은 지금 실수라고 여겨진다.스택 "is-NOT-a" 벡터. 임의로 요소를 삽입 및 제거하지 마십시오.차라리 작문이었어야 했는데.

안타깝게도 이 설계 오류를 수정하기에는 너무 늦었다. 지금 상속 계층을 변경하면 기존 코드와의 호환성이 깨질 것이기 때문이다.상속 대신 구성을 사용했다면 API를 위반하지 않고 다른 데이터 구조를 사용하도록 언제든 수정할 수 있다.

나는 Josh Bloch의 책 Effective Java 2판을 강력히 추천한다.

  • 항목 16: 상속보다 구성 선호
  • 항목 17: 상속 또는 금지 설계 및 문서

좋은 객체 지향 설계는 기존 클래스를 자유롭게 확장하는 것이 아니다.당신의 첫 번째 본능은 작곡하는 것이어야 한다.


참고 항목:

은 구성 수수를 한다.HAS A
은 상수수 을 의미한다.IS A

Example: 자동차는 엔진이 있고 차는 자동차다.

프로그래밍에서 이는 다음과 같이 표현된다.

class Engine {} // The Engine class.

class Automobile {} // Automobile class which is parent to Car class.

class Car extends Automobile { // Car is an Automobile, so Car class extends Automobile class.
  private Engine engine; // Car has an Engine so, Car class has an instance of Engine class as its member.
}

어떻게 유산이 위험할 수 있는가?

예를 들어보자.

public class X{    
   public void do(){    
   }    
}    
Public Class Y extends X{
   public void work(){    
       do();    
   }
}

1) 위의 코드에서 분명히 알 수 있듯이, 클래스 Y는 클래스 X와 매우 강한 결합을 가진다.만약 슈퍼클래스 X에서 어떤 변화가 생긴다면 Y는 극적으로 부서질 수 있다.향후 클래스에서는 X가 아래 서명으로 메서드 작업을 구현한다고 가정하십시오.

public int work(){
}

변경은 클래스 X에서 이루어지지만 클래스 Y를 컴파일할 수 없게 만들 것이다.그래서 이런 종류의 의존은 어떤 수준까지 올라갈 수 있고 매우 위험할 수 있다.슈퍼클래스가 모든 서브클래스와 서브클래스 내에서 코드를 완벽하게 파악하지 못할 때마다 슈퍼클래스에서 무슨 일이 일어나고 있는지 항상 계속 눈치채고 있을 수 있다.그래서 우리는 이 강하고 불필요한 결합을 피해야 한다.

작곡은 이 문제를 어떻게 해결하는가?

같은 예를 수정하여 보자.

public class X{
    public void do(){
    }
}

Public Class Y{
    X x = new X();    
    public void work(){    
        x.do();
    }
}

여기서 우리는 Y 클래스에 X 클래스의 참조를 만들고 X 클래스의 인스턴스를 만들어 X 클래스의 호출 방법을 만들고 있다.이제 그 강한 결합은 모두 사라졌다.슈퍼클래스와 서브클래스는 이제 서로 매우 독립적이다.수업은 상속 상황에서 위험했던 변화를 자유롭게 할 수 있다.

2) 유연성이라 부르는 방법을 제공한다는 점에서 작곡의 두 번째 매우 좋은 장점, 예를 들면 다음과 같다.

class X implements R
{}
class Y implements R
{}

public class Test{    
    R r;    
}

r reference를 이용한 Test class에서 나는 Y class뿐만 아니라 X class의 메서드를 호출할 수 있다.이러한 융통성은 유산에 있어 결코 존재하지 않았다.

3) 또 다른 큰 장점 : 단위시험

public class X {
    public void do(){
    }
}

Public Class Y {
    X x = new X();    
    public void work(){    
        x.do();    
    }    
}

위의 예에서 x 인스턴스의 상태를 알 수 없는 경우 일부 테스트 데이터를 사용하여 쉽게 조롱할 수 있으며 모든 방법을 쉽게 테스트할 수 있다.예를 들어, 어떤 방법도 실행하기 위해 슈퍼클래스에 크게 의존하고 있었기 때문에 이것은 상속에서 전혀 가능하지 않았다.

4) 상속을 피해야 하는 또 다른 좋은 이유는 자바가 복수의 상속을 지원하지 않기 때문이다.

예를 들어 다음과 같이 설명하십시오.

Public class Transaction {
    Banking b;
    public static void main(String a[])    
    {    
        b = new Deposit();    
        if(b.deposit()){    
            b = new Credit();
            c.credit();    
        }
    }
}

반가운 소식:

  1. 상속을 통해 컴파일 시간에 그 특징을 제공하는 동안, 구성이 런타임에 쉽게 달성된다.

  2. 구성은 HAS-A 관계로도 알려져 있고, 상속은 IS-A 관계로도 알려져 있다.

그러므로 상상의 여러 가지 이유로 상속보다 항상 작곡을 선호하는 습관을 들이도록 하라.

@michael Rodrigues가 제시한 답은 정확하지 않으며(사과한다; 직접 논평할 수 없다), 약간의 혼란으로 이어질 수 있다.

인터페이스 구현은 일종의 상속...인터페이스를 구현할 때, 당신은 모든 상수를 상속받을 뿐만 아니라, 당신은 당신의 개체가 인터페이스에 의해 지정된 타입이 되도록 커밋하고 있다; 그것은 여전히 "is-a" 관계다.자동차가 Fillable을 구현하는 경우, 자동차는 "Is-a" Fillable이며, 여러분이 Fillable을 사용하고자 하는 모든 곳에서 당신의 코드에 사용될 수 있다.

구성은 상속과 근본적으로 다르다.구성을 사용할 때는 상속을 사용할 때 만드는 'is-a' 관계가 아니라 (다른 답안처럼)개체 간에 'has-a' 관계를 만드는 것이다.

그래서, 다른 질문의 자동차 예시를 보면, 만약 내가 자동차 "has-a" 가스 탱크라고 말하고 싶다면, 다음과 같이 구성을 사용할 것이다.

public class Car {

private GasTank myCarsGasTank;

}

그것이 어떤 오해가 풀렸으면 좋겠다.

상속IS-A 관계를 낳는다.작문은 HAS-A 관계를 이끌어낸다.전략 패턴은 특정 행동을 정의하는 알고리즘 패밀리가 있는 경우 구성을 사용해야 한다고 설명한다.
비행 동작을 구현하는 오리 클래스의 전형적인 예.

public interface Flyable{
 public void fly();
}

public class Duck {
 Flyable fly;

 public Duck(){
  fly = new BackwardFlying();
 }
}

따라서 우리는 비행을 구현하는 여러 클래스를 가질 수 있다.

public class BackwardFlying implements Flyable{
  public void fly(){
    Systemout.println("Flies backward ");
  }
}
public class FastFlying implements Flyable{
  public void fly(){
    Systemout.println("Flies 100 miles/sec");
  }
}

만약 유산을 위한 것이라면, 우리는 파리 기능을 계속해서 구현하는 두 종류의 새들을 가질 것이다.그래서 상속과 구성은 전혀 다르다.

구성이란 소리가 들리는 대로 된다. 부품을 꽂아 개체를 만드는 것이다.

답변의 나머지 부분은 다음 전제에 근거하여 잘못 편집한다.
이 작업은 인터페이스를 통해 수행된다.
예를 들어 다음과 같은 경우Car의 예시로는 '미친놈'의

Car implements iDrivable, iUsesFuel, iProtectsOccupants
Motorbike implements iDrivable, iUsesFuel, iShortcutThroughTraffic
House implements iProtectsOccupants
Generator implements iUsesFuel

그래서 몇 가지 표준 이론적 요소들을 가지고 여러분은 여러분의 목표를 세울 수 있다.그 다음엔 어떻게 해야 할지를 채워주는 것이 너의 일이다.House거주자를 보호하는 방법Car거주자를 보호한다.

상속은 다른 방식과 같다.완전(또는 반완성) 개체로 시작하여 변경할 다양한 비트를 바꾸거나 재정의하십시오.

예를 들어,MotorVehicleA과 함께 올 수 있다.Fuelable방법 및Drive방법오토바이와 승용차를 가득 채우는 것이 똑같기 때문에 Fuel 방식을 그대로 둘 수도 있지만, 그 방식을 무시할 수도 있다.Drive오토바이는 a와 매우 다르게 운전하기 때문이다.Car.

상속과 함께 어떤 클래스는 이미 완전히 구현되고, 다른 클래스는 당신이 무시하도록 강요되는 메서드를 가지고 있다.컴퍼지션으로는 아무것도 제공되지 않는다. (하지만 다른 클래스의 메서드를 호출하여 인터페이스를 구현할 수 있다.

구성이 더 유연한 것으로 보여지는데, iUsusFuel과 같은 방법을 가지고 있다면 자동차, 보트, 스토브, 바비큐 등과는 상관없이 연료가 들어갈 수 있는 물체를 다루기만 하는 방법(다른 클래스, 또 다른 프로젝트)을 다른 곳에서 가질 수 있기 때문이다.인터페이스는 그 인터페이스를 구현한다고 말하는 클래스가 인터페이스에 관한 모든 방법을 실제로 가질 것을 명령한다.예를 들어,

iFuelable Interface:
   void AddSomeFuel()
   void UseSomeFuel()
   int  percentageFull()

그럼 다른 곳에서 방법을 찾을 수 있을거야

private void FillHerUp(iFuelable : objectToFill) {

   Do while (objectToFill.percentageFull() <= 100)  {

        objectToFill.AddSomeFuel();
   }

이상한 예시지만, 이 방법은 물체가 구현하기 때문에 무엇이 채워지든 상관하지 않는다는 것을 보여준다.iUsesFuel, 채워질 수 있다.이야기의 끝.

상속을 대신 사용한 경우 다른 항목이 필요함FillHerUp대승적 MotorVehicles그리고Barbecues, 다니다"가 없다면 "의 기본 수 있을 것이다상속할 기본 개체인 ThatUsusFuel".

구성과 상속은 동일한가?

그들은 같지 않다.

구성 : 물체의 그룹이 하나의 물체의 예와 같은 방식으로 취급되어야 하는 것을 가능하게 한다.복합체의 목적은 객체를 트리 구조로 "복사"하여 부분-전위 계층을 나타내는 것이다.

상속:클래스는 직접적이든 간접적이든 모든 슈퍼클래스로부터 분야와 방법을 상속받는다.하위 클래스는 자신이 상속하는 메서드를 재정의하거나 상속하는 필드나 메서드를 숨길 수 있다.

구성 패턴을 구현하려면 자바에서 어떻게 해야 할까?

위키피디아 기사는 자바에서 복합 패턴을 구현하기에 충분하다.

여기에 이미지 설명을 입력하십시오.

주요 참가자:

구성 요소:

  1. 복합 구성 요소를 포함한 모든 구성 요소의 추상화 여부
  2. 구성에서 개체의 인터페이스를 선언함

리프:

  1. 구성에서 리프 객체를 나타냄
  2. 모든 구성 요소 메서드 구현

복합:

  1. 복합 구성 요소(자녀가 있는 구성 요소)를 나타냄
  2. 어린이를 조작하는 방법 구현
  3. 일반적으로 모든 구성요소 방법을 하위 구성요소에 위임하여 구현

복합 패턴을 이해하는 코드 예제:

import java.util.List;
import java.util.ArrayList;

interface Part{
    public double getPrice();
    public String getName();
}
class Engine implements Part{
    String name;
    double price;
    public Engine(String name,double price){
        this.name = name;
        this.price = price;
    }
    public double getPrice(){
        return price;
    }
    public String getName(){
        return name;
    }
}
class Trunk implements Part{
    String name;
    double price;
    public Trunk(String name,double price){
        this.name = name;
        this.price = price;
    }
    public double getPrice(){
        return price;
    }
    public String getName(){
        return name;
    }
}
class Body implements Part{
    String name;
    double price;
    public Body(String name,double price){
        this.name = name;
        this.price = price;
    }
    public double getPrice(){
        return price;
    }
    public String getName(){
        return name;
    }
}
class Car implements Part{
    List<Part> parts;
    String name;

    public Car(String name){
        this.name = name;
        parts = new ArrayList<Part>();
    }
    public void addPart(Part part){
        parts.add(part);
    }
    public String getName(){
        return name;
    }
    public String getPartNames(){
        StringBuilder sb = new StringBuilder();
        for ( Part part: parts){
            sb.append(part.getName()).append(" ");
        }
        return sb.toString();
    }
    public double getPrice(){
        double price = 0;
        for ( Part part: parts){
            price += part.getPrice();
        }
        return price;
    }   
}

public class CompositeDemo{
    public static void main(String args[]){
        Part engine = new Engine("DiselEngine",15000);
        Part trunk = new Trunk("Trunk",10000);
        Part body = new Body("Body",12000);

        Car car = new Car("Innova");
        car.addPart(engine);
        car.addPart(trunk);
        car.addPart(body);

        double price = car.getPrice();

        System.out.println("Car name:"+car.getName());
        System.out.println("Car parts:"+car.getPartNames());
        System.out.println("Car price:"+car.getPrice());
    }

}

출력:

Car name:Innova
Car parts:DiselEngine Trunk Body
Car price:37000.0

설명:

  1. 부분은 나뭇잎이다.
  2. 자동차에 많은 부품이 포함됨
  3. 자동차의 다른 부품들이 자동차에 추가되었다.
  4. 자동차 가격 = (각 부품 가격)의 합계

구성 및 상속의 장단점에 대해서는 아래 질문을 참조하십시오.

상속보다 작곡을 선호하십니까?

또 다른 예로서, 자동차 클래스를 고려한다면, 이것은 구성의 좋은 사용이 될 것이고, 자동차는 엔진, 변속기, 타이어, 좌석 등을 "갖고" 있을 것이다.그것은 그 수업들 중 어떤 것도 연장하지 않을 것이다.

구성이란 어떤 것이 뚜렷한 부분으로 이루어져 있고 그 부분들과 강한 관계를 갖는 것이다.주역이 죽으면 다른 사람도 죽는다, 자기 자신의 삶을 가질 수 없다.대략적인 예가 인간의 몸이다.심장을 꺼내면 다른 모든 부분이 사라진다.

상속이란 이미 존재하는 것을 그냥 가져다가 사용하는 것이다.강한 관계는 없다.사람은 아버지의 재산을 상속받을 수 있지만 그는 그것 없이도 할 수 있다.

나는 자바를 잘 몰라서 예를 들지는 못하지만 개념에 대한 설명은 할 수 있어.

간단한 단어집합은 관계가 있다는 것을 의미한다.

구성은 특별한 통합 사례다.좀 더 구체적으로 말하면, 제한된 집계를 구성이라고 한다.물체가 다른 물체를 포함할 때, 컨테이너 물체의 존재 없이 포함된 물체가 존재할 수 없다면, 그것을 구성이라고 한다.예: 한 학급에 학생이 포함되어 있다. 학생은 수업 없이는 존재할 수 없다. 수업과 학생 사이에는 작문이 존재한다.

집계를 사용하는 이유

코드 재사용성

집계를 사용할 때

관련 선박이 없을 때 집계를 통해 코드 재사용을 달성하는 것이 가장 좋다.

상속

상속은 부모 자식 관계 상속 수단 A 관계

자바에서의 상속은 한 개체가 부모 개체의 모든 속성과 행동을 획득하는 메커니즘이다.

Java 1 Code Reusability에서 상속을 사용하는 것. 2 Method Overriding뿐만 아니라 Child Class에서 추가 기능 추가(그래서 런타임 다형성을 달성할 수 있다).

한 클래스가 다른 클래스를 확장하는 두 클래스 간의 상속은 "IS A" 관계를 설정한다.

다른 쪽 끝의 구성은 당신의 반에서 "Has A" 관계를 설정하는 다른 클래스의 예를 포함한다.자바에서의 구성은 기술적으로 다중 상속을 용이하게 하기 때문에 유용하다.

상속과 구성 모두 코드 재사용 가능성을 제공하지만, 자바에서 구성과 상속의 주요 차이점은 구성에서는 코드를 연장하지 않고 코드를 재사용할 수 있지만 상속의 경우 코드 또는 기능의 재사용을 위해 클래스를 확장해야 한다는 것이다.이러한 사실에서 발생하는 또 다른 차이점은 컴퍼지션을 사용하면 확장 불가능한 최종 클래스에도 코드를 재사용할 수 있지만 이러한 경우 상속은 코드를 재사용할 수 없다는 것이다.또한 구성을 사용하면 여러 클래스의 코드를 멤버 변수로 선언하므로 재사용할 수 있지만, Java에서는 여러 클래스를 Java에서 지원하지 않기 때문에 한 클래스만 확장할 수 있기 때문에 상속에서는 한 클래스만 코드를 재사용할 수 있다.한 클래스가 두 클래스 이상 연장될 수 있기 때문에 C++로 할 수 있다.BTW, 당신은 항상 Java의 상속보다 작곡을 선호해야 한다. 그것은 나뿐만 아니라 조슈아 Bloch가 그의 책에서 제안한 것이다.

나는 이 사례가 상속구성의 차이를 명확하게 설명해 준다고 생각한다.

이 모든 일에서, 문제는 상속과 구성을 사용하여 해결된다.저자는 상속에서 슈퍼클래스의 변화가 그것을 상속하는 파생 클래스에 문제를 일으킬 수 있다는 사실에 주목한다.

그곳에서 당신은 상속이나 구성에 UML을 사용할 때 표현의 차이를 볼 수 있다.

http://www.javaworld.com/article/2076814/core-java/inheritance-versus-composition--which-one-should-you-choose-.html

상속 대 구성.

상속과 구성은 모두 계급행동의 재이용과 확장에 사용된다.

IS-A 관계 유형과 같은 패밀리 알고리즘 프로그래밍 모델에서 주로 사용되는 상속은 유사한 종류의 물체를 의미한다.예.

  1. 더러는 자동차다.
  2. 사파리는 자동차다.

이들은 카 계열의 사람들이다.

구성은 HAS-A 관계 유형을 나타낸다.그것은 더러가 5단 기어, 사파리가 4단 기어와 같은 물체의 능력을 보여준다.우리가 기존 수업의 능력을 확장할 필요가 있을 때마다 작곡을 사용하라.를 들어, 우리는 더스트러 오브젝트에 기어를 하나 더 추가해야 하고 그 다음에 기어 오브젝트를 더 만들어서 더스트러 오브젝트에 구성해야 한다.

모든 파생 클래스가 그러한 기능을 필요로 하기 전까지는/아니면 기본 클래스를 변경해서는 안 된다.이 시나리오에서는 컴포지션을 사용해야 한다.예를 들어

클래스 B가 파생한 클래스 A

클래스 C가 파생한 클래스 A

클래스 D에 의해 파생된 클래스 A.

클래스 A에 기능을 추가하면 클래스 C와 D가 해당 기능을 요구하지 않아도 모든 하위 클래스에 사용할 수 있다.이 시나리오에서 우리는 그러한 기능에 대한 별도의 클래스를 만들어 필요한 클래스로 구성할 필요가 있다(여기서는 클래스 B).

아래의 예는 다음과 같다.

          // This is a base class
                 public abstract class Car
                    {
                       //Define prototype
                       public abstract void color();
                       public void Gear() {
                           Console.WriteLine("Car has a four Gear");
                       }
                    }


           // Here is the use of inheritence
           // This Desire class have four gears.
          //  But we need to add one more gear that is Neutral gear.

          public class Desire : Car
                   {
                       Neutral obj = null;
                       public Desire()
                       {
     // Here we are incorporating neutral gear(It is the use of composition). 
     // Now this class would have five gear. 

                           obj = new Neutral();
                           obj.NeutralGear();
                       }

                       public override void color()
                       {
                           Console.WriteLine("This is a white color car");
                       }

                   }


             // This Safari class have four gears and it is not required the neutral
             //  gear and hence we don't need to compose here.

                   public class Safari :Car{
                       public Safari()
                       { }

                       public override void color()
                       {
                           Console.WriteLine("This is a red color car");
                       }


                   }

   // This class represents the neutral gear and it would be used as a composition.

   public class Neutral {
                      public void NeutralGear() {
                           Console.WriteLine("This is a Neutral Gear");
                       }
                   }

구성이란 특정 클래스와 관련된 클래스에 개체를 생성하는 것을 의미한다.학생이 계정과 관련이 있다고 가정해 보십시오.

상속: 이 클래스는 기능이 확장된 이전 클래스 입니다.그것은 이 새로운 클래스가 기능이 확장된 올드 클래스라는 것을 의미한다.학생이 학생이지만 모든 학생이 인간이라고 가정해보자.그래서 학생과 인간과의 관계가 있다.이것은 상속이다.

상속은 클래스의 완전한 기능을 재사용하는 것을 의미한다. 여기서 나의 클래스는 슈퍼 클래스의 모든 방법을 사용해야 하고 나의 클래스는 슈퍼 클래스와 잘 결합될 것이며 상속의 경우 두 클래스에 코드가 중복될 것이다.

그러나 우리가 다른 클래스와 대화하기 위해 작곡을 사용할 때 우리는 이 모든 문제를 극복할 수 있다. 작곡은 다른 클래스의 속성을 우리가 이야기하고 싶은 클래스로 선언하는 것이다. 그리고 그 클래스에서 우리가 원하는 기능성은 그 속성을 사용함으로써 얻을 수 있다.

아니, 둘 다 다르다. 구성은 "HAS-A" 관계를 따르고 유산은 "IS-A" 관계를 따른다. 구성의 가장 좋은 예는 전략적인 패턴이다.

참조URL: https://stackoverflow.com/questions/2399544/difference-between-inheritance-and-composition

반응형