#![allow(unused)]fnmain() {
use std::rc::Rc;
use std::sync::Arc;
use std::pin::Pin;
// Examples of dyn compatible methods.traitTraitMethods {
fnby_ref(self: &Self) {}
fnby_ref_mut(self: &mutSelf) {}
fnby_box(self: Box<Self>) {}
fnby_rc(self: Rc<Self>) {}
fnby_arc(self: Arc<Self>) {}
fnby_pin(self: Pin<&Self>) {}
fnwith_lifetime<'a>(self: &'aSelf) {}
fnnested_pin(self: Pin<Arc<Self>>) {}
}
structS;
impl TraitMethods for S {}
let t: Box<dyn TraitMethods> = Box::new(S);
}
#![allow(unused)]fnmain() {
// This trait is dyn compatible, but these methods cannot be dispatched on a trait object.traitNonDispatchable {
// Non-methods cannot be dispatched.fnfoo() whereSelf: Sized {}
// Self type isn't known until runtime.fnreturns(&self) -> SelfwhereSelf: Sized;
// `other` may be a different concrete type of the receiver.fnparam(&self, other: Self) whereSelf: Sized {}
// Generics are not compatible with vtables.fntyped<T>(&self, x: T) whereSelf: Sized {}
}
structS;
impl NonDispatchable for S {
fnreturns(&self) -> SelfwhereSelf: Sized { S }
}
let obj: Box<dyn NonDispatchable> = Box::new(S);
obj.returns(); // ERROR: cannot call with Self return
obj.param(S); // ERROR: cannot call with Self parameter
obj.typed(1); // ERROR: cannot call with generic type}
#![allow(unused)]fnmain() {
use std::rc::Rc;
// Examples of dyn-incompatible traits.traitDynIncompatible {
const CONST: i32 = 1; // ERROR: cannot have associated constfnfoo() {} // ERROR: associated function without Sizedfnreturns(&self) -> Self; // ERROR: Self in return typefntyped<T>(&self, x: T) {} // ERROR: has generic type parametersfnnested(self: Rc<Box<Self>>) {} // ERROR: nested receiver not yet supported
}
structS;
impl DynIncompatible for S {
fnreturns(&self) -> Self { S }
}
let obj: Box<dyn DynIncompatible> = Box::new(S); // ERROR}
#![allow(unused)]fnmain() {
// `Self: Sized` traits are dyn-incompatible.traitTraitWithSizewhereSelf: Sized {}
structS;
impl TraitWithSize for S {}
let obj: Box<dyn TraitWithSize> = Box::new(S); // ERROR}
#![allow(unused)]fnmain() {
// Dyn-incompatible if `Self` is a type argument.traitSuper<A> {}
traitWithSelf: Super<Self> whereSelf: Sized {}
structS;
impl<A> Super<A> for S {}
impl WithSelf for S {}
let obj: Box<dyn WithSelf> = Box::new(S); // ERROR: cannot use `Self` type parameter}
#![allow(unused)]fnmain() {
traitShape { fnarea(&self) -> f64; }
traitCirclewhereSelf: Shape {
fnradius(&self) -> f64 {
// A = pi * r^2// so algebraically,// r = sqrt(A / pi)
(self.area() /std::f64::consts::PI).sqrt()
}
}
}
下一个示例在泛型参数上调用父特征方法。
#![allow(unused)]fnmain() {
traitShape { fnarea(&self) -> f64; }
traitCircle : Shape { fnradius(&self) -> f64; }
fnprint_area_and_radius<C: Circle>(c: C) {
// Here we call the area method from the supertrait `Shape` of `Circle`.println!("Area: {}", c.area());
println!("Radius: {}", c.radius());
}
}
类似地,这是一个在特征对象上调用父特征方法的示例。
#![allow(unused)]fnmain() {
traitShape { fnarea(&self) -> f64; }
traitCircle : Shape { fnradius(&self) -> f64; }
structUnitCircle;
impl Shape for UnitCircle { fnarea(&self) -> f64 { std::f64::consts::PI } }
impl Circle for UnitCircle { fnradius(&self) -> f64 { 1.0 } }
let circle = UnitCircle;
let circle = Box::new(circle) asBox<dyn Circle>;
let nonsense = circle.radius() * circle.area();
}