본문 바로가기
Java

Class(4)-Composition

by GGShin 2022. 4. 27.

Composition이란

Inheritance(상속)가 class간 부모-자식 관계를 만들어 주었다면, 

Composition(조합)은 class 들끼리 서로의 구성요소가 될 때 각 class가 가진 fields나 methods를 사용할 수 있도록 하는 방법입니다.

"has a" 관계일 때 사용한다고 말하기도 하는데요 (inheritance는 "is a" 관계). 예를 들어서, 고양이와 눈(eyes)의 관계는 무엇일까요? 고양이가 눈을 가지고 있다 (A cat has eyes) 라고 할 수 있겠죠. 고양이가 눈이거나 눈이 고양이인 것은 아닙니다(is a 관계가 아니라는 말입니다). 그러므로 이런 경우에는 inheritance를 사용하기보다는 composition을 사용해야 적절합니다. 

 

이번에는 한 번 Computer라는 class와 MacBook이라는 class를 한 번 생각해보겠습니다.

MacBook은 컴퓨터 중에 한 가지 종류죠. 그렇기 때문에 Computer class가 가진 속성을 상속받는다면 좀 더 편리하게 MacBook class를 만들 수 있을 것이라 생각해 볼 수 있습니다. 

반면에, MacBook class와 Keyboard라는 class가 있다면 이 둘의 관계는 어떨까요? Keyboard가 MacBook으로 부터 나왔다고 보기도 어렵고 그 반대라고 얘기하기도 어려울 것입니다. 그렇지만 MacBook 안에는 keyboard가 들어있습니다(MacBook has a keyboard). 다시 말해 keyboard는 MacBook의 구성요소 중 하나입니다. 이럴 때 Composition을 사용할 수 있습니다. 

 

조금 더 구체적으로 얘기해 볼까요? MacBook을 구성하는 눈에 보이는 큼지막한 요소들은 Screen, Keyboard, TrackPad 이렇게 나눌 수 있겠습니다. 이를 class로 나타낸다면 MacBook 이라는 class는 Screen, Keyboard, TrackPad 라는 세개의 class가 조합되어 만들어진다고 할 수 있겠죠. 코드로 한 번 보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MacBook {

 
    private Screen screen;
    private Keyboard keyboard;
    private TrackPad trackPad;
 
    public MacBook(Screen screen, Keyboard keyboard, TrackPad trackPad) {
        this.screen = screen;
        this.keyboard = keyboard;
        this.trackPad = trackPad;
    }
 
}
 
cs

 

지금까지는 field에 integer, double, boolean과 같은 primitive type이나 String이 들어가는 형태만 봤었는데요, 이렇게 class가 들어갈 수도 있습니다. 그리고 이런식으로 class를 field로 설정하여 사용하는 것을 composition(조합)이라고합니다.

 

Composition의 장점

그렇다면 Composition의 장점은 무엇일까요? 

Inheritance 는 한 가지의 class만 상속 할 수 있습니다. (둘 이상의 class를 상속하는 것은 Java에서 가능하지 않습니다.)

하지만 composition을 사용하면 둘 이상의 class에 접근하여 각 class의 속성들을 이용할 수 있다는 장점이 있습니다.

 

한번 만들어 본 MacBook class를 사용해서 object를 만들어보겠습니다.

이런 식으로 MacBook object에 들어갈 class들도 모두 initialize 해주면 사용이 가능해집니다.

1
2
3
4
5
6
7
8
9
10
11
public class Main {
    public static void main(String[] args) {
        
        //파라미터로 들어가는 class objects 생성
        Screen screen = new Screen(2540,1440);        
        Keyboard keyboard = new Keyboard();
        TrackPad trackPad = new TrackPad();
        //MacBook class object 생성할 때 파라미터에 위에서 만들어 준 각각의 파라미터 class들 사용
        MacBook myMacBook = new MacBook(screen, keyboard, trackPad);
 
}
cs

 

혹은, 아래와 같이 macBook에 들어갈 parameter들을 괄호 안에서 바로 initialize 해 주어도 무방합니다.

1
2
3
4
5
6
public class Main {
    public static void main(String[] args) {
 
        MacBook macBook = new MacBook(new Screen(2540,1440), new Keyboard(), new TrackPad());
 
}
cs

 

각 Class별 methods에 접근하기

이렇게 Composition을 사용한 object를 만들보았는데요,

어떻게 하면 parameter로 사용된 각 class의 method에 접근할 수 있을까요?

Inheritance(상속) 했을 때에는 override method를 사용하여서 접근할 수 있었습니다만, composition에서는 어떤 방법으로 접근하면 될까요?

 

1) 한 가지 방법은 MacBook class에 작성한 getter methods를 거쳐서 접근하는 것입니다.

Screen class에는 getResolution()이라는 public method가 있고,

Screen class

macBook 객체가 Screen class에 있는 getResolution() method에 접근하려고 한다면,

아래와 같이 MacBook에서 Screen에 접근하게 해주는 getScreen() method를 불러주고, 그런 다음에 Screen에 있는 getResolution() method를 불러주는 것입니다.

getter 사용하여 접근하기

2) 다른 한가지 방법은 MacBook class 내부에 getResolution()에 접근하는 method를 따로 제작하여 사용하는 방법입니다.

예시로 한 번 보면, 아래처럼 MacBook class 내부에 public method인 powerOn()을 만들어 그 안에서 screen에 있는 getResolution()에 접근하도록 하였습니다. 

이렇게 method를 만들어 준 후에, Main class로 돌아가서 사용해주기만 하면 됩니다.

이렇게 하면 첫번째 방법과 동일한 결과를 확인할 수 있습니다.

 

언제 Composition을 사용하는게 좋은가요?

그렇다면 언제 Inheritance를 사용하고 언제 Composition을 사용하면 될까요?

우선적으로는 Composition의 사용을 고려하는 것이 낫다고 합니다. 아무래도 한 번에 한 class만을 inherit 하는 것 보다는 composition을 사용해 다양한 class에 접근할 수 있다는 장점이 있기 때문이죠. 

 

Geeks for Geeks에 관련한 내용이 잘 나와있어서 한 번 살펴보았습니다.

[Java와 OOP에서 Inheritance 보다 Composition 사용을 권장하는 이유]

1. Java에서 하나의 class만을 상속하게 하는 이유는 composition의 사용을 장려하기 때문입니다. (-> 하나만 상속할 수 있게 만든 의도 자체가 composition 사용을 권장하기 위함이었네요!) Inheritance는 하나의 class만을 사용할 수 있지만 composition을 사용하면 더욱 다양한 class의 기능을 사용할 수 있게 됩니다.

2. Inheritance보다 composition를 이용한 class 테스트 기능이 더 편리합니다. Composition을 사용하면 테스트용 object를 만들어서 한 class 안에서 사용하고자 하는 다른 class의 기능들을 확인해 볼 수 있는 반면 inheritance에서는 불가능 합니다.

3. Inheritance는 encapsulation을 깨트리기 때문에 class 내부의 요소의 외부 접근성이 높아져 불안정하게 됩니다.

...

설명을 읽으니 왜 composition을 더 많이 사용해야 할 지 조금 더 와닿는 것 같습니다.

 

더욱 자세한 내용을 보기 원하시면 링크로 들어가 확인해시면 좋겠습니다.

https://www.geeksforgeeks.org/favoring-composition-over-inheritance-in-java-with-examples/#:~:text=Favoring%20Composition%20over%20Inheritance%20is,a%20base%20or%20parent%20class. 

 

Favoring Composition Over Inheritance In Java With Examples - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org

 

다음번에는 이어서 composition 사용 권장 이유 중에 하나였던 Encapsulation(캡슐화)에 대해서 알아보겠습니다.

감사합니다.☺️

반응형