Menu
Coddy logo textTech

컴포지션 vs 상속

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 87개 중 47번째.

상속은 "is-a" 관계를 만듭니다. Dog하나의 Animal입니다. 하지만 클래스가 자신이 아닌 무언가의 기능을 필요로 한다면 어떻게 해야 할까요? 이때 composition이 사용되며, 대신 "has-a" 관계를 설정합니다.

composition을 사용하면 클래스는 다른 클래스를 확장하는 대신 해당 클래스의 인스턴스를 필드로 포함합니다:

// 상속 접근 방식: Car IS an Engine (말이 안 됨)
class Car extends Engine { }

// 구성 접근 방식: Car HAS an Engine (말이 됨)
class Car {
    private Engine engine;
    
    public Car(Engine engine) {
        this.engine = engine;
    }
    
    public void start() {
        engine.ignite();
    }
}

Composition은 여러 가지 장점을 제공합니다. 예를 들어 엔진을 교체하는 것처럼 런타임에 구성된 객체를 변경할 수 있습니다.

또한 여러 클래스의 동작을 결합할 수도 있는데, 이는 Java의 inheritance에서는 허용되지 않습니다. composed class는 자신이 선택한 methods만 노출하므로 더 나은 캡슐화를 제공합니다.

실용적인 지침: 진정한 "is-a" 관계가 있고 하위 클래스가 상위 클래스의 특화된 버전을 실제로 나타낼 때 상속을 사용하세요.

다른 클래스의 기능을 사용해야 하지만 그 클래스와 같은 유형이 될 필요는 없을 때 composition을 사용하세요. 많은 숙련된 개발자는 더 유연하고 유지 관리하기 쉬운 코드로 이어지기 때문에 다음 원칙을 따릅니다. "favor composition over inheritance"

challenge icon

챌린지

쉬움

composition을 사용하여 "has-a" 관계를 보여 주는 컴퓨터 시스템을 만들어 봅시다. Computer가 구성 요소를 상속받는 대신(이는 적절하지 않습니다), 컴퓨터가 기능하는 데 필요한 부품을 포함하도록 만들 것입니다.

코드를 세 개의 파일로 구성합니다.

  • Processor.java: CPU를 나타내는 클래스를 Create하세요. Processor에는 두 개의 private fields가 있습니다: brand (String)와 speedGHz (double)입니다. 두 fields를 초기화하는 constructor와 각각에 대한 getter methods를 포함하세요. String을 반환하는 process() method를 추가하세요: [brand] processing at [speedGHz] GHz
  • Memory.java: RAM을 나타내는 클래스를 Create하세요. Memory에는 두 개의 private fields가 있습니다: type (String, "DDR4" 또는 "DDR5"와 같음)과 sizeGB (int)입니다. constructor와 getters, 그리고 다음을 반환하는 load() method를 포함하세요: Loading [sizeGB]GB [type] memory
  • Computer.java: 여기서 composition의 장점이 드러납니다! Computer class는 Processor와 Memory를 private fields로 가져야 합니다. 이들을 extend하는 것이 아니라, 포함하는 것입니다. 두 components를 accepts하는 constructor를 포함하세요. 다음과 같이 components를 사용하여 컴퓨터가 시작되는 모습을 여러 줄의 String으로 반환하는 boot() method를 추가하세요.
    Booting computer...
    [processor.process() result]
    [memory.load() result]
    System ready!
    또한 다음을 반환하는 getSpecs() method를 추가하세요: Specs: [processor brand] CPU, [memory sizeGB]GB [memory type]
  • Main.java: composition으로 구성한 시스템을 실행하세요! 네 가지 inputs를 받습니다: processor brand (String), processor speed (double), memory type (String), memory size (int)입니다.

    이 values로 Processor와 Memory를 Create한 다음, 이들을 Computer로 composition하세요. boot()을 호출한 결과를 출력한 다음, getSpecs()의 결과를 출력하세요.

네 가지 inputs를 다음 순서로 받습니다: processor brand, processor speed (GHz), memory type, memory size (GB)입니다.

Computer가 components가 되려고 하기보다는 components에 작업을 위임하는 방식을 확인하세요. 이것이 composition의 힘입니다! Computer는 여러분이 제공하는 어떤 Processor나 Memory든 사용할 수 있으므로, 설계가 유연하고 현실적입니다.

직접 해보기

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 입력 읽기
        String processorBrand = scanner.nextLine();
        double processorSpeed = Double.parseDouble(scanner.nextLine());
        String memoryType = scanner.nextLine();
        int memorySize = Integer.parseInt(scanner.nextLine());
        
        // TODO: brand와 speed로 Processor 생성
        
        // TODO: type과 size로 Memory 생성
        
        // TODO: Processor와 Memory를 조합하여 Computer 생성
        
        // TODO: boot() 결과 출력
        
        // TODO: getSpecs() 결과 출력
    }
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Java 컴파일러