Menu
Coddy logo textTech

Реализация трейтов

Часть раздела Объектно-ориентированное программирование путешествия по Rust на Coddy. Урок 30 из 61.

Теперь, когда вы знаете, как определить trait, давайте посмотрим, как сделать так, чтобы структура выполняла этот контракт. Реализация trait связывает абстрактное требование с конкретным поведением.

Синтаксис использует impl TraitName for StructName:

trait Speak {
    fn speak(&self) -> String;
}

struct Dog {
    name: String,
}

impl Speak for Dog {
    fn speak(&self) -> String {
        format!("{} says: Woof!", self.name)
    }
}

Блок impl Speak for Dog сообщает Rust, что Dog реализует трейт Speak. Внутри него вы указываете фактическое тело метода. Здесь вы определяете, как говорит собака.

Мощь трейтов становится очевидной, когда несколько типов реализуют один и тот же трейт:

struct Cat {
    name: String,
}

impl Speak for Cat {
    fn speak(&self) -> String {
        format!("{} says: Meow!", self.name)
    }
}

И Dog, и Cat теперь обладают возможностью Speak, но каждый из них предоставляет собственную уникальную реализацию. Вы можете вызвать .speak() для любого из этих типов:

let dog = Dog { name: String::from("Rex") };
let cat = Cat { name: String::from("Whiskers") };

println!("{}", dog.speak());  // Rex говорит: Гав!
println!("{}", cat.speak());  // Whiskers говорит: Мяу!

Это основа полиморфизма в Rust: разные типы, один и тот же интерфейс, уникальное поведение.

challenge icon

Задание

Легко

Давайте воплотим трейты в жизнь, реализовав их для разных типов! Вы создадите трейт Describable и реализуете его для двух разных структур, каждая из которых будет предоставлять собственное уникальное описание.

Вы организуете код в трёх файлах:

  • describable.rs: Определите публичный трейт Describable с методом describe(&self) -> String.
  • items.rs: Создайте две публичные структуры, реализующие ваш трейт:
    • Book с публичным полем title (String)
    • Movie с публичным полем name (String)
    Каждая структура должна реализовывать Describable в собственном уникальном формате описания.
  • main.rs: Объедините модули, создайте экземпляры обеих структур и вызовите их методы describe, чтобы показать, как один и тот же трейт создаёт разные результаты для разных типов.

Ваш Book должен описывать себя как Book: {title}, а ваш Movie — как Film: {name}. Обратите внимание, как каждый тип выполняет один и тот же контракт, но обладает собственным поведением!

В основном файле создайте книгу и фильм, используя два предоставленных входных значения, а затем выведите их описания в отдельных строках.

Ваш вывод должен соответствовать следующему формату:

Book: {title}
Film: {name}

Например, для входных значений 1984 и Inception:

Book: 1984
Film: Inception

Вы получите два входных значения: название книги и название фильма.

Попробуйте сами

mod describable;
mod items;

use describable::Describable;
use items::{Book, Movie};

fn main() {
    // Читаем входные данные
    let mut title = String::new();
    std::io::stdin().read_line(&mut title).expect("Failed to read line");
    let title = title.trim().to_string();
    
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();
    
    // TODO: Создать экземпляр Book с title
    
    // TODO: Создать экземпляр Movie с name
    
    // TODO: Вывести описание книги
    
    // TODO: Вывести описание фильма
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Rust