Menu
CoddyTech

组合

本课属于 Coddy Rust 学习旅程的“面向对象编程”单元。第 55 课,共 61 课。

许多面向对象语言都大量依赖继承,在不同类型之间共享功能。Rust 采用了不同的方法:组合。你不从父类继承行为,而是将其他类型作为字段包含进来,从而构建复杂类型。

考虑对汽车进行建模。你可以不创建基础 Vehicle 类并从中继承,而是用更小、更专注的组件组合出一个 Car:

struct Engine {
    horsepower: u32,
}

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

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

Car 不继承自 Engine 或 Wheels。它拥有它们。这种“拥有”关系就是组合。你可以通过字段访问内部组件,并直接调用它们的方法:

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

impl Car {
    fn start(&self) {
        self.engine.start();  // 委托给内部组件处理
    }
}

这种模式让每个结构体都专注于单一职责。需要更改引擎的工作方式吗?只需修改 Engine 结构体。想在摩托车中复用 Wheels 吗?只需将它包含在新的结构体中。组合让你拥有灵活性,同时避免了继承通常会造成的紧密耦合。

challenge icon

挑战

简单

让我们用组合来构建一个计算机系统!你不必创建一个庞大的结构体,而是用较小且职责明确的组件来组合出一个 Computer:一个 CPU 和一个 Memory。每个组件都能描述自身,而 Computer 会把工作委托给它的各个组成部分。

你需要将代码分布在三个文件中:

  • cpu.rs:定义一个公开的 CPU 结构体,其中有两个公开字段:cores(u32),表示核心数;speed_ghz(f32),表示时钟速度。添加一个 specs 方法,返回一个描述 CPU 的 String,格式为 {cores}-core @ {speed_ghz}GHz。
  • memory.rs:定义一个公开的 Memory 结构体,其中有一个公开字段 size_gb(u32),表示内存大小。添加一个 specs 方法,返回格式为 {size_gb}GB RAM 的 String。
  • main.rs:引入这两个模块,并创建一个公开的 Computer 结构体,它包含一个类型为 CPU 的 cpu 字段,以及一个类型为 Memory 的 memory 字段。在 Computer 上实现一个 system_info 方法,将工作委托给各个组件,并打印完整的系统规格。使用提供的输入来构建一个 Computer,并显示其信息。

system_info 方法应打印:

System: {cpu_specs} | {memory_specs}

例如,输入 8、3.5 和 16 时:

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

输入 4、2.8 和 32 时:

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

你会收到三个输入:CPU 核心数(解析为 u32)、CPU 速度(解析为 f32)和内存大小(解析为 u32)。

亲手试试

mod cpu;
mod memory;

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

// TODO:定义一个包含两个公共字段的公共 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 在线编译器