Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Обобщённые трейты

Трейты, как и типы и функции, тоже могут быть обобщёнными. Параметры трейта получают конкретные типы при использовании. Например, трейт From<T> используется для определения преобразований типов:

#![allow(unused)]
fn main() {
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0

pub trait From<T>: Sized {
    fn from(value: T) -> Self;
}
}
// Copyright 2024 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[derive(Debug)]
struct Foo(String);

impl From<u32> for Foo {
    fn from(from: u32) -> Foo {
        Foo(format!("Converted from integer: {from}"))
    }
}

impl From<bool> for Foo {
    fn from(from: bool) -> Foo {
        Foo(format!("Converted from bool: {from}"))
    }
}

fn main() {
    let from_int = Foo::from(123);
    let from_bool = Foo::from(true);
    dbg!(from_int);
    dbg!(from_bool);
}
This slide should take about 5 minutes.
  • Трейт From будет рассмотрен позже в курсе, но его определение в документации std простое, и для справки оно приведено здесь.

  • Реализации трейта не обязаны покрывать все возможные параметры типа. Здесь Foo::from("hello") не скомпилируется, потому что для Foo нет реализации From<&str>.

  • Обобщённые трейты принимают типы как «входные» данные, тогда как ассоциированные типы — это «выходные» типы. Трейт может иметь несколько реализаций для разных входных типов.

  • На самом деле Rust требует, чтобы для любого типа T совпадала не более чем одна реализация трейта. В отличие от некоторых других языков, у Rust нет эвристики для выбора «наиболее специфичного» совпадения. Ведётся работа над поддержкой этого, называемой специализацией.