Menu
CoddyTech

Screen 结构体

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

challenge icon

挑战

简单

现在该把所有 UI 组件组合起来了!你将创建一个 Screen 结构体,用 trait 对象保存一组不同的可绘制组件。这正是 Vec<Box<dyn Draw>> 发挥强大作用的地方:用一个集合管理多种组件类型。

你将在不断扩展的项目中添加一个新模块:

  • draw.rs:你在之前的挑战中创建的 Draw trait。
  • text_field.rs:你的 TextField 组件,它会打印 Text: {content}。
  • button.rs:你的 Button 组件,它会打印 Button: {label} (width: {width})。
  • screen.rs:创建一个 Screen 结构体,其中包含一个类型为 Vec<Box<dyn Draw>> 的公共字段 components。实现一个创建空屏幕的关联函数 new,以及一个接收 Box<dyn Draw> 并将其添加到组件向量中的 add 方法。
  • main.rs:组合所有模块。创建一个 Screen,向其中添加一个 TextField 和一个 Button,然后遍历屏幕中的组件,并对每个组件调用 draw()。

你的 Screen 需要存储 trait 对象,因此要将 dyn 关键字与 Draw trait 一起使用。add 方法应该接收 &mut self,因为它会修改组件向量。

将提供以下输入:

  • 第一行:文本字段的内容
  • 第二行:按钮的标签
  • 第三行:按钮的宽度(数字)

你的输出应按添加顺序将每个组件显示在单独一行:

Text: Hello
Button: Click Me (width: 80)

亲手试试

mod draw;
mod text_field;
mod button;
mod screen;

use draw::Draw;
use text_field::TextField;
use button::Button;
use screen::Screen;

pub struct Label {
    pub text: String,
}

impl Draw for Label {
    fn draw(&self) {
        println!("{}", self.text);
    }
}

fn main() {
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let content = input1.trim().to_string();

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let label = input2.trim().to_string();

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let width: u32 = input3.trim().parse().expect("Failed to parse width");

    // TODO: 使用 Screen::new() 创建一个 Screen
    // TODO: 将用 Box::new() 包装的 TextField 添加到 screen 中
    // TODO: 将用 Box::new() 包装的 Button 添加到 screen 中
    // TODO: 遍历 screen.components,对每个组件调用 draw()
}

面向对象编程中的所有课

自己练习: Rust 在线编译器