スクリーンの実行
CoddyのRustジャーニー「Object Oriented Programming」セクションの一部 — レッスン 53/61。
チャレンジ
簡単ドキュメントシステムプロジェクトの最終ステップに到達しました。おめでとうございます!これまでに、Draw トレイト、TextField、Button、そして Screen という個別のパーツをすべて構築してきました。次は、Screen に、一度のメソッド呼び出しですべてのコンポーネントをレンダリングする機能を持たせる番です。
Screen 構造体に run メソッドを追加して、プロジェクトを完成させましょう。このメソッドは、スクリーンに保存されているすべてのコンポーネントを反復処理し、それぞれに対して draw() を呼び出すことで、ドキュメントシステム全体を機能させます。
プロジェクトファイル構成:
draw.rs:drawメソッドを持つDrawトレイト。text_field.rs:Text: {content}と出力するTextFieldコンポーネント。button.rs:Button: {label} (width: {width})と出力するButtonコンポーネント。screen.rs:newおよびaddメソッドを持つScreen構造体。&selfを受け取り、コレクション内のすべてのコンポーネントに対してdraw()を呼び出すrunメソッドを追加してください。main.rs: すべてをまとめます。Screenを作成し、コンポーネントを追加して、run()を呼び出すことで、画面全体を一度にレンダリングします。
run メソッドはレンダリングのロジックを Screen 内にカプセル化するため、メイン関数をクリーンでシンプルに保つことができます。main 内で手動でコンポーネントを反復処理する代わりに、screen.run() を呼び出すだけで済みます。
以下の入力が提供されます:
- 1行目:テキストフィールドのコンテンツ
- 2行目:ボタンのラベル
- 3行目:ボタンの幅(数値)
出力は、追加された順に各コンポーネントをそれぞれの行に表示する必要があります:
Text: Dashboard
Button: Save (width: 120)自分で試してみよう
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");
let mut screen = Screen::new();
let text_field = TextField { content };
screen.add(Box::new(text_field));
let button = Button { label, width };
screen.add(Box::new(button));
// TODO: 以下の手動の反復処理を、screen.run() の単一の呼び出しに置き換える
for component in &screen.components {
component.draw();
}
}