Menu
Coddy logo textTech

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

Часть раздела Object Oriented Programming путешествия по Rust на Coddy — урок 30 из 61.

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

Синтаксис использует 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 говорит: Woof!
println!("{}", cat.speak());  // Whiskers говорит: Meow!

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

challenge icon

Задание

Легко

Давайте воплотим типажи (traits) в жизнь, реализовав их для различных типов! Вы создадите типаж 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

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

Шпаргалка

Чтобы реализовать типаж (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)
    }
}

Несколько типов могут реализовывать один и тот же типаж с различным поведением:

struct Cat {
    name: String,
}

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

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

println!("{}", dog.speak());  // Rex says: Woof!
println!("{}", cat.speak());  // Whiskers says: Meow!

Это обеспечивает полиморфизм в Rust — когда разные типы используют один и тот же интерфейс с уникальными реализациями.

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

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Проверьте себя

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

Все уроки раздела Object Oriented Programming