Composition(조합)

2022. 12. 3. 16:31카테고리 없음

-포함(Composite)이란?

 

-클래스의 멤버로 참조변수를 선언하는 것

 

 

ex)일반 클래스 

Class Circle{
	int x;//원점의 x좌표
    int y;//원점의 y좌표
    int r;//반지름 (radius)
    
}

 

X ->C.X / Y->C.Y / R->C.R

 

 

ex)조합 예시

Class Point{
	 int x;
     int y;

}


Class Circle{

	Point c = new Pont ();
	int r;// 반지름 (radius)

}

point class를 circle를 포함한다. 

R->C.R/ X->C.C.X/Y->C.C.Y

-작은 단위의 클래스를 만들고, 이 들을 조합해서 클래스를 만든다.

Class Car {
		Engine e = new Engine();//엔진
        Door[] d = new Door[4];//문, 문의 개수를 넷으로 가정하고 배열로 처리했다.
        
}

 

클래스 간의 관계 결정하기 

 

상속관계 '~은~이다(is-a)'  =Circle is a Point

포함관계 '~은 ~을 가지고 있다(has-a)'=Circle has a Point 

 

ex) 원은 점이다?, 원은 점을 가지고 있다.

 

Class Circle{//포함
	Point c = new Point ();
    int r;

}

Class Circle extends Point{//상속
	int r;
}

 

ex)

package main;

public class MyPoint {//조합
	int x;
	int y;

}

/*
 * class Circle extends MyPoint{//상속 int r;
 * 
 * }
 */

class Circle{///포함 
	MyPoint p; //=// new MyPoint(); 참조변수의 초기화  이것을 안해주면
    //저장공간이 만들어지지 않는다  null값만 남는다 (변수 P =NULL)이렇게 
	int r;
	
	Circle(){
		p = new MyPoint();//기본적으로 만들지 않으면 생성자에서 초기화 해줘야 한다.
	}
	
}

 class InheritanceTest{
	public static void main(String[] args) {
		Circle c= new Circle();
		/*
		 * c.x=1; c.y=2;
		 */
		c.p.x=1;
		c.p.y=2;
		c.r=3;
		System.out.println("c.x=" +c.p.x);
		/*
		 * System.out.println("c.x=" +c.x); System.out.println("c.x=" +c.y);
		 */
		System.out.println("c.y=" +c.p.y);
		System.out.println("c.r=" +c.r);
		
		
	}
	
	
	
}

 

 

 

[ 상속(Inheritance) 이란? ]

상속은 상위 클래스에 중복 로직을 구현해두고 이를 물려받아 코드를 재사용하는 방법이다. 흔히 상속은 Is-a 관계라고 많이 불린다.

예를 들어 요리사 클래스와 사람 클래스가 있을 때 요리사는 사람이므로 이러한 관계를 Is-a 관계라고 한다.

public class Person {

    public void walk() {
        System.out.println("걷는다");
    }

    public void talk() {
        System.out.println("말한다");
    }
}

public class Chef extends Person {
    
}

 

 

요리사 클래스는 사람 클래스를 상속받았으므로 사람 클래스에 정의된 메소드들을 다음과 같이 재사용할 수 있다.

Person person = new Chef();

person.walk();
person.talk();

 

 

이렇게 부모 클래스에 정의된 메소드를 물려받아 재사용하는 것을 상속이라고 부른다.

[ 합성(Composition) 이란? ]

합성은 중복되는 로직들을 갖는 객체를 구현하고, 이 객체를 주입받아 중복 로직을 호출함으로써 퍼블릭 인터페이스를 재사용하는 방법이다. 흔히 합성은 Has-a 관계라고 많이 불린다.

예를 들어 요리사가 음식의 가격을 계산해야 하는 상황이라고 하자. 그러면 요리사는 자신이 만든 음식들을 가지고 있으므로 이러한 관계를 Has-a 관계라고 한다.

public class Chef {

    private List<Food> foodList;
    
    public Chef(List<Food> foodList) {
        this.foodList = foodList;
    }

    public int calculatePrice() {
        return foodList.stream()
            .mapToInt(v -> v.getPrice())
            .sum();
	}
}

 

 

상속으로 코드를 재사용하는 것과 합성으로 퍼블릭 인터페이스를 재사용하는 것은 근본적으로 다르다. 왜냐하면 합성을 이용하면 객체의 내부는 공개되지 않고 인터페이스를 통해 코드를 재사용하기 때문에 구현에 대한 의존성을 인터페이스에 대한 의존성으로 변경하여 결합도를 낮출 수 있기 때문이다.

또한 합성을 이용하면 여러가지 단점들이 부각되는데, 상속을 이용하면 어떠한 단점들이 생기고 왜 합성을 이용해야 하는지에 대해 알아보도록 하자.

 

[ 상속의 단점 및 한계점 ]

상속은 중복을 제거하기에 아주 좋은 객체지향 기술처럼 보이고, 그에 따라 상속을 무분별하게 남발하는 경우를 자주 볼 수 있다. 하지만 상속을 이용해야 하는 경우는 상당히 선택적이며, 상속이 갖는 단점은 상당히 치명적이기 때문에 상속보다는 합성을 이용할 것을 권장한다.

상속은 대표적으로 다음과 같은 단점을 가지고 있다.

  • 캡슐화가 깨지고 결합도가 높아짐
  • 유연성 및 확장성이 떨어짐(부품을 마음대로 갈아 끼울 수 없다)
  • 다중상속에 의한 문제가 발생할 수 있음(상속은 한번 밖에 안되기에 문제 발생)
  • 클래스 폭팔 문제가 발생할 수 있음

정리

 

부모클래스의 구현을 변경하면 많은 자식 클래스를 모드 변경을 해줘야 하는 상황이 생길 수 있다.

상속은 불필요한 부모 클래스의 퍼블릭 메소드가 자식 클래스도 어쩔수 없이 노출하게 된다.

-> 특히 공개된 부모 클래스의 퍼블릿 메소드가 자식 클래스의 내부 규칙과 맞지 않을 수도 있다.

조합
:전체를 표현하는 클래스가 부분을 표현하는 객체를 포함해서 부분 객체의 코드를 재사용하는 방법이다.

조합의 장점
: 상속과 달리 부분 객체의 내부 구현이 공개되지 않는다. 메소드 호출하는 방식으로 public 인터페이스에 
의존해서 부분 객체의 내부 구현이 변경되어도 비교적 안전하다.

[OOP] 코드의 재사용, 상속(Inheritance)보다 합성(Composition)을 사용해야 하는 이유 - MangKyu's Diary (tistory.com)

 

[OOP] 코드의 재사용, 상속(Inheritance)보다 합성(Composition)을 사용해야 하는 이유

객체지향 프로그래밍에서 코드를 재사용하기 위한 방법으로 크게 상속과 합성이 있습니다. 대부분의 경우 상속보다 합성을 이용하는 것이 좋은데, 이번에는 왜 합성을 사용해야 하는지에 대해

mangkyu.tistory.com

[JAVA] 상속과 조합 (Inheritance vs Composition) (velog.io)