Menu
Coddy logo textTech

컴포지션

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

많은 객체 지향 언어는 타입 간에 기능을 공유하기 위해 상속에 크게 의존합니다. Rust는 컴포지션이라는 다른 접근 방식을 취합니다. 부모로부터 동작을 상속하는 대신, 다른 타입을 필드로 포함하여 복잡한 타입을 구성합니다.

자동차를 모델링한다고 생각해 보세요. 기본 Vehicle 클래스를 만들고 이를 상속하는 대신, 더 작고 특정 기능에 집중하는 컴포넌트들로 Car를 구성합니다:

struct Engine {
    horsepower: u32,
}

struct Wheels {
    count: u8,
    diameter: f32,
}

struct Car {
    engine: Engine,
    wheels: Wheels,
    brand: String,
}

CarEngine이나 Wheels에서 상속되지 않습니다. 대신 이들을 가지고 있습니다. 이러한 "has-a" 관계가 컴포지션입니다. fields를 통해 inner component에 접근하고 해당 method를 직접 호출할 수 있습니다:

impl Engine {
    fn start(&self) {
        println!("Engine with {} HP started!", self.horsepower);
    }
}

impl Car {
    fn start(&self) {
        self.engine.start();  // 내부 컴포넌트에 위임
    }
}

이 패턴은 각 구조체가 하나의 책임에 집중하도록 합니다. 엔진의 작동 방식을 변경해야 하나요? Engine 구조체만 수정하면 됩니다. 오토바이에 Wheels를 재사용하고 싶나요? 새 구조체에 포함하기만 하면 됩니다. 컴포지션은 상속이 흔히 만들어 내는 강한 결합 없이 유연성을 제공합니다.

challenge icon

챌린지

쉬움

컴포지션을 사용하여 컴퓨터 시스템을 만들어 봅시다! 하나의 거대한 구조체를 만드는 대신, 더 작고 특정 기능에 집중하는 구성 요소인 CPUMemoryComputer를 구성합니다. 각 구성 요소는 자신을 설명하는 방법을 알고 있으며, Computer는 해당 부분에 작업을 위임합니다.

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

  • cpu.rs: 두 개의 public 필드를 가진 public CPU 구조체를 Define합니다. 하나는 코어 수를 나타내는 cores (u32)이고, 다른 하나는 클록 속도를 나타내는 speed_ghz (f32)입니다. CPU를 {cores}-core @ {speed_ghz}GHz 형식으로 설명하는 String을 returns하는 specs method를 추가합니다.
  • memory.rs: memory 크기를 나타내는 public field size_gb (u32)를 가진 public Memory 구조체를 Define합니다. {size_gb}GB RAM 형식의 String을 returns하는 specs method를 추가합니다.
  • main.rs: 두 모듈을 모두 가져오고, has cpu field of type CPUmemory field of type Memory를 가진 public Computer 구조체를 생성합니다. Computer에 system_info method를 Implement하여 해당 구성 요소에 위임하고 전체 시스템 사양을 출력합니다. 제공된 inputs를 사용하여 Computer를 만들고 해당 정보를 표시합니다.

system_info method는 다음을 출력해야 합니다:

System: {cpu_specs} | {memory_specs}

예를 들어 inputs가 8, 3.5, 16인 경우:

System: 8-core @ 3.5GHz | 16GB RAM

그리고 inputs가 4, 2.8, 32인 경우:

System: 4-core @ 2.8GHz | 32GB RAM

세 개의 inputs를 받습니다: CPU cores (u32로 parse), CPU speed (f32로 parse), memory size (u32로 parse).

직접 해보기

mod cpu;
mod memory;

use cpu::CPU;
use memory::Memory;

// TODO: 두 개의 public 필드를 가진 public Computer 구조체를 정의하세요:
// - cpu: CPU
// - memory: Memory

// TODO: Computer에 system_info 메서드를 구현하세요:
// - cpu.specs()와 memory.specs()에 위임합니다
// - 출력: System: {cpu_specs} | {memory_specs}

fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let cores: u32 = input.trim().parse().expect("Invalid number");
    
    input.clear();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let speed_ghz: f32 = input.trim().parse().expect("Invalid number");
    
    input.clear();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let size_gb: u32 = input.trim().parse().expect("Invalid number");
    
    // TODO: 파싱된 입력을 사용하여 CPU와 Memory 인스턴스를 생성하세요
    
    // TODO: CPU와 Memory로 Computer 인스턴스를 생성하세요
    
    // TODO: computer에서 system_info()를 호출하여 결과를 출력하세요
}
quiz icon실력 점검

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

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

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