РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
551 of 1245 menu

Безопасность объектов трейта

Безопасность объектов трейта (object safety) - это характеристика трейта, которая определяет, можно ли использовать этот трейт как тип для dyn Trait и вызывать его методы через динамическую диспетчеризацию. Трейт, удовлетворяющий правилам объектной безопасности, называется объектно-безопасным (object-safe). Если трейт не является объектно-безопасным, компилятор выдаст ошибку при попытке создать dyn Trait или Box<dyn Trait>. Основные правила: методы не должны возвращать Self по значению, не должны иметь обобщённых параметров типа, не должны быть статическими, а также трейт не должен требовать Sized для Self.

Синтаксис

trait TraitName { fn method(&self); } let value: Box<dyn TraitName>;

Пример

Давайте создадим объектно-безопасный трейт Shape с методом area и используем его через Box<dyn Shape>:

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 main() { let shapes: Vec<Box<dyn Shape>> = vec![ Box::new(Circle { radius: 2.0 }), ]; for shape in &shapes { println!("{}", shape.area()); } }

Результат выполнения кода:

12.56

Пример

Давайте попробуем создать трейт с методом, возвращающим Self, что нарушает объектную безопасность:

trait Cloneable { fn clone_self(&self) -> Self; } fn main() { let _value: Box<dyn Cloneable>; }

Результат выполнения кода:

error[E0038]: the trait `Cloneable` cannot be made into an object

Пример

Давайте создадим объектно-безопасный трейт с методом по умолчанию и используем его через &dyn Trait:

trait Greeter { fn name(&self) -> String; fn greet(&self) -> String { format!("Hello, {}!", self.name()) } } struct Person { name: String, } impl Greeter for Person { fn name(&self) -> String { self.name.clone() } } fn main() { let person = Person { name: String::from("abcde") }; let greeter: &dyn Greeter = &person; println!("{}", greeter.greet()); }

Результат выполнения кода:

"Hello, abcde!"

Смотрите также

  • ключевое слово dyn,
    которое используется для динамической диспетчеризации трейтов
  • ключевое слово trait,
    которое объявляет трейт в Rust
  • конструкция trait bound,
    которая ограничивает обобщённые типы трейтами
  • типаж Sized,
    который влияет на объектную безопасность трейта
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить