Уроки модуля (2/2)
Черты и границы черт
Черты определяют поведение, которое имеет конкретный тип и которое может быть общим с другими типами. Мы можем использовать черты для определения набора методов, которые представляют определенную общую функциональность или интерфейс, похожий на интерфейсы в других языках программирования.
Границы признаков позволяют нам указать, что универсальный тип должен реализовывать определенный признак, гарантируя, что необходимые методы будут доступны во время компиляции.
Определение и реализация черты
Чтобы определить признак, мы используем ключевое слово trait, за которым следуют сигнатуры методов, которые должны определять реализующие типы:
pub trait Summary {
fn summarize(&self) -> String;
}Чтобы реализовать признак конкретного типа, мы используем синтаксис impl TraitName for TypeName:
pub struct NewsArticle {
pub headline: String,
pub content: String,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}", self.headline)
}
}Границы черт
При написании универсальных функций мы можем ограничить параметры типа, чтобы гарантировать, что они реализуют определенную особенность. Стандартный синтаксис: <T: Trait>:
pub fn notify<T: Summary>(item: &T) {
println!("Notification: {}", item.summarize());
}Альтернативно, для более сложных подписей мы можем использовать предложение where:
pub fn notify_advanced<T>(item: &T)
where
T: Summary
{
println!("Notification: {}", item.summarize());
}Попробуйте сами
Упражнение 1: Суммарная черта
Определите признак с именем Summary, содержащий сигнатуру метода fn summ(&self) -> String;. Затем определите структуру NewsArticle с полем заголовка типа String и реализуйте для нее свойство Summary, чтобы метод summous возвращал значение поля заголовка.
Показать подсказку
Определите атрибут «Summary» и структуру «NewsArticle». Реализуйте с помощью impl Summary for NewsArticle, клонируя поле self.headline.clone().
Решение доступно после 3 попыток
Упражнение 2. Границы признаков с помощью print_summary
На основе кода из предыдущего упражнения определите универсальную функцию с именем print_summary<T>, которая принимает элемент параметра типа &T. Примените черту, связанную так, чтобы T реализовывал черту Summary. Внутри функции распечатайте результат, возвращаемый item.summarize().
Показать подсказку
Используйте подпись `fn print_summary<T: Summary>(item: &T)`и вызовите`item.summarize()` внутри`println!`.
Решение доступно после 3 попыток
Упражнение 3. Расчет площади с использованием признаков
Определите признак с именем Area с помощью метода fn area(&self) -> f64;. Создайте структуру Circle, содержащую поле радиуса типа f64, и реализуйте для нее признак Area, вычислив площадь (формула: радиус * радиус * 3,14159).
Показать подсказку
Определите атрибут Area и структуру Circle. Реализуйте `area(&self)`, используя формулу площади круга.
Решение доступно после 3 попыток