컴포지션 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"
챌린지
쉬움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] GHzMemory.java: RAM을 나타내는 클래스를 Create하세요. Memory에는 두 개의 private fields가 있습니다:type(String, "DDR4" 또는 "DDR5"와 같음)과sizeGB(int)입니다. constructor와 getters, 그리고 다음을 반환하는load()method를 포함하세요:Loading [sizeGB]GB [type] memoryComputer.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() 결과 출력
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
4상속
상속의 기초 (extends)super 키워드메서드 오버라이딩 (@Override)생성자 체이닝Object 클래스단일 및 다중 레벨 상속다중 클래스 상속이 불가능한 이유요약 - 직원 계층 구조직접 연습해 보세요: 온라인 Java 컴파일러