Структура Screen
Часть раздела Object Oriented Programming путешествия по Rust на Coddy — урок 52 из 61.
Задание
ЛегкоТеперь пришло время собрать все ваши UI-компоненты вместе! Вы создадите структуру Screen, которая может содержать коллекцию различных отрисовываемых компонентов, используя объекты типажа (trait objects). Именно здесь мощь Vec<Box<dyn Draw>> проявляется в полной мере — одна коллекция, которая управляет несколькими типами компонентов.
Вы добавите новый модуль в свой растущий проект:
draw.rs: Ваш типажDrawиз предыдущих задач.text_field.rs: Ваш компонентTextField, который выводитText: {content}.button.rs: Ваш компонентButton, который выводитButton: {label} (width: {width}).screen.rs: Создайте структуруScreen, которая содержит публичное полеcomponentsтипаVec<Box<dyn Draw>>. Реализуйте ассоциированную функциюnew, которая создает пустой экран, и методadd, который принимаетBox<dyn Draw>и добавляет его в вектор компонентов.main.rs: Соберите все модули вместе. СоздайтеScreen, добавьте в негоTextFieldиButton, затем переберите компоненты экрана и вызовитеdraw()для каждого из них.
Вашему Screen необходимо хранить объекты типажа, поэтому вы будете использовать ключевое слово dyn с вашим типажом Draw. Метод 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, используя Screen::new()
// TODO: Добавьте TextField, обернутый в Box::new(), в screen
// TODO: Добавьте Button, обернутую в Box::new(), в screen
// TODO: Переберите screen.components и вызовите draw() для каждого компонента
}Все уроки раздела Object Oriented Programming
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media Player