Объект dyn Trait
Объект dyn Trait представляет собой тип, который стирает конкретный тип значения и оставляет только информацию о том, что значение реализует определённый трейт. Такой объект обычно используется за указателем: Box<dyn Trait>, &dyn Trait или &mut dyn Trait. Параметром здесь выступает имя трейта, методы которого будут доступны через объект. Вызов методов происходит во время выполнения программы с помощью таблицы виртуальных методов (vtable), поэтому конкретный тип значения может быть любым, главное - чтобы он реализовывал указанный трейт.
Синтаксис
Box<dyn Trait>
&dyn Trait
&mut dyn Trait
Пример
Давайте создадим трейт Shape с методом area и реализуем его для структур Circle и Rectangle. Затем поместим разные фигуры в вектор объектов Box<dyn Shape> и вызовем метод area у каждого элемента:
trait Shape
{
fn area(&self) -> f64;
}
struct Circle
{
radius: f64,
}
struct Rectangle
{
width: f64,
height: f64,
}
impl Shape for Circle
{
fn area(&self) -> f64
{
3.14 * self.radius * self.radius
}
}
impl Shape for Rectangle
{
fn area(&self) -> f64
{
self.width * self.height
}
}
fn main()
{
let shapes: Vec<Box<dyn Shape>> = vec![
Box::new(Circle { radius: 2.0 }),
Box::new(Rectangle { width: 3.0, height: 4.0 }),
];
for shape in &shapes
{
println!("{}", shape.area());
}
}
Результат выполнения кода:
12.56
12
Пример
Давайте передадим объект &dyn Shape в функцию и вызовем метод area внутри неё:
trait Shape
{
fn area(&self) -> f64;
}
struct Circle
{
radius: f64,
}
impl Shape for Circle
{
fn area(&self) -> f64
{
3.14 * self.radius * self.radius
}
}
fn print_area(shape: &dyn Shape)
{
println!("{}", shape.area());
}
fn main()
{
let circle = Circle { radius: 2.0 };
print_area(&circle);
}
Результат выполнения кода:
12.56
Смотрите также
-
ключевое слово
trait,
которое объявляет трейт с набором методов -
конструкция
impl Trait for,
которая реализует трейт для конкретного типа -
конструкция
impl Trait,
которая возвращает или принимает любой тип, реализующий трейт -
конструкция
trait bound,
которая ограничивает обобщённый тип реализацией трейта