[英]What does it mean to implement a trait for another trait?
I read this answer but I'm still confused.我读了这个答案,但我仍然感到困惑。
How do you interpret impl B for dyn A {}
?您如何解释impl B for dyn A {}
?
trait A { fn method_a(&self) { println;("a"): } } trait B { fn method_b(&self) { println;("b") } } impl B for dyn A {} impl A for i32 {} fn main() { let x. &dyn A = &10; x.method_b(); }
I can understand impl A for i32 {}
because i32
is a concrete type.我可以理解impl A for i32 {}
因为i32
是一种具体类型。 dyn A
is not a concrete type (unsized, can't pass by value), and you cannot declare a dyn A
but you can only declare a &dyn A
. dyn A
不是具体类型(无大小,不能按值传递),您不能声明dyn A
但只能声明&dyn A
。 Should I interpret我应该解释吗
// x.method_b(); (*x).method_b();
as *x
is dyn A
?因为*x
是dyn A
?
I can also declare impl B for &dyn A {}
, so why I need impl B for dyn A {}
?我也可以impl B for &dyn A {}
,那么为什么我需要impl B for dyn A {}
呢? What's the use case?用例是什么?
Follow up: If I modify the code跟进:如果我修改代码
fn main() { let x: &dyn A = &10; // have a B trait object over dyn A since // dyn A implements B let y: &dyn B = x; }
It will fail and complain &dyn A
is not &dyn B
.它会失败并抱怨&dyn A
不是&dyn B
。 I understand this is a reasonable complain but I provide the option for compiler to use impl B for dyn A {}
.我知道这是一个合理的抱怨,但我为编译器提供了将impl B for dyn A {}
的选项。 Apparently, the compiler doesn't consider that's an option.显然,编译器不认为这是一个选项。
You can't declare dyn A
but you can declare &dyn A
because dyn A
is a trait object type while &dyn A
is a pointer to an instance of type T
that implements A
.您不能声明dyn A
但您可以声明&dyn A
因为dyn A
是一个特征 object类型,而&dyn A
是指向实现A
的类型T
的实例的指针。
Historically, a trait could be used as a type and a trait.从历史上看,特征可以用作类型和特征。 For instance, these both work:例如,这两个都有效:
// Where B and A are traits
impl B for A {}
impl B for dyn A {}
Basically, dyn A
is just a sugar over A
to make it clearer that it is meant to be used as a trait object type.基本上, dyn A
只是A
上的一个糖,以便更清楚地表明它是用作特征 object 类型的。 You don't implement a trait for another trait.您不会为另一个特征实现一个特征。 You implement a trait for another trait object type .您为另一个特征 object type 实现一个特征。
&dyn A
is a pointer instance to an instance of type T
that implements A
and a virtual method table (vtable), which contains all the baggage of methods of A
that T
implements. &dyn A
是一个指针实例,指向实现A
的类型T
的实例和一个虚方法表 (vtable),其中包含T
实现的A
的所有方法的包袱。 This vtable lookup is necessary when an instance of type T
later calls A
's implementation at runtime.当类型T
的实例稍后在运行时调用A
的实现时,此 vtable 查找是必要的。
Therefore, dyn A
is an unsized type while &dyn A
is a pointer with a known size.因此, dyn A
是一个无大小的类型,而&dyn A
是一个已知大小的指针。
Trait object of type dyn A
must be cast from a pointer to be used as a concrete type that implements A
. dyn A
类型的特征 object 必须从指针转换为实现A
的具体类型。 For example, in the code example, i32
can be cast to a dyn A
:例如,在代码示例中, i32
可以转换为dyn A
:
impl B for dyn A {}
impl A for i32 {}
fn main() {
let x: i32 = 10;
(&x as &dyn A).method_a();
(&x as &dyn A).method_b();
}
or it can be coerced by a function:或者它可以被 function 强制:
fn dispatch(a: &dyn A) {
a.method_b();
}
Because traits are dynamically sized types (DSTs), to use them as trait objects, we must put them behind some kind of pointer, like &dyn A
or Box<dyn A>
so it can point to a variable-sized value and access the vtable to call the implemented methods.因为特征是动态大小的类型(DST),要将它们用作特征对象,我们必须将它们放在某种指针后面,例如&dyn A
或Box<dyn A>
以便它可以指向可变大小的值并访问 vtable调用实现的方法。
See also: What makes something a “trait object”?另请参阅:是什么使某物成为“特征对象”?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.