Ассоциированные типы
Ассоциированные типы - это механизм трейтов,
который позволяет объявить внутри трейта
некоторый тип-заполнитель. Конкретный тип
указывается уже в реализации трейта для
структуры или перечисления. Параметром
выступает ключевое слово type, за
которым следует имя типа и, при необходимости,
ограничения трейтов. В отличие от обобщённых
параметров, ассоциированный тип не передаётся
извне, а определяется самой реализацией,
что делает код лаконичнее.
Синтаксис
trait TraitName
{
type AssocType;
fn method(&self) -> Self::AssocType;
}
В реализации трейта ассоциированный тип
задаётся через type:
impl TraitName for StructName
{
type AssocType = ConcreteType;
fn method(&self) -> Self::AssocType
{
// ...
}
}
Пример
Давайте объявим трейт Container с
ассоциированным типом Item и реализуем
его для структуры Numbers, которая
хранит вектор целых чисел:
trait Container
{
type Item;
fn first(&self) -> Option<&Self::Item>;
}
struct Numbers
{
items: Vec<i32>,
}
impl Container for Numbers
{
type Item = i32;
fn first(&self) -> Option<&Self::Item>
{
self.items.first()
}
}
fn main()
{
let nums = Numbers { items: vec![1, 2, 3, 4, 5] };
let res = nums.first();
println!("{:?}", res);
}
Результат выполнения кода:
Some(1)
Пример
Давайте реализуем тот же трейт Container
для структуры Words, но в качестве
ассоциированного типа укажем String:
trait Container
{
type Item;
fn first(&self) -> Option<&Self::Item>;
}
struct Words
{
items: Vec<String>,
}
impl Container for Words
{
type Item = String;
fn first(&self) -> Option<&Self::Item>
{
self.items.first()
}
}
fn main()
{
let words = Words {
items: vec![String::from("abcde"), String::from("12345")],
};
let res = words.first();
println!("{:?}", res);
}
Результат выполнения кода:
Some("abcde")
Пример
Давайте объявим трейт Pair с двумя
ассоциированными типами и реализуем его
для кортежа из двух разных типов:
trait Pair
{
type First;
type Second;
fn describe(&self) -> String;
}
struct TwoValues<A, B>
{
first: A,
second: B,
}
impl<A: std::fmt::Debug, B: std::fmt::Debug> Pair for TwoValues<A, B>
{
type First = A;
type Second = B;
fn describe(&self) -> String
{
format!("{:?} and {:?}", self.first, self.second)
}
}
fn main()
{
let pair = TwoValues { first: 1, second: "abcde" };
let res = pair.describe();
println!("{}", res);
}
Результат выполнения кода:
"1 and \"abcde\""
Смотрите также
-
ключевое слово
trait,
которое объявляет трейт с методами и типами -
конструкция
impl for,
которая реализует трейт для конкретного типа -
конструкция
impl Trait,
которая возвращает анонимный тип, реализующий трейт -
конструкция
trait bound,
которая задаёт ограничения на обобщённые параметры