为什么必须在特征对象引用的集合中指定关联类型? [英] Why must the associated type be specified in a collection of trait object references?
问题描述
这是一个令人反感的示例(游乐场):
Here is an offending example (Playground):
// Some traits
trait Behaviour {
type Sub: SubBehaviour;
}
trait SubBehaviour {}
// Some implementations of these traits
struct A;
impl Behaviour for A {
type Sub = B;
}
struct B;
impl SubBehaviour for B {}
// Struct that holds a collection of these traits.
struct Example<'a> {
behaviours: Vec<&'a dyn Behaviour>,
}
impl<'a> Example<'a> {
fn add_behaviour<T: Behaviour>(&mut self, b: &'a T) {
self.behaviours.push(b);
}
}
fn main() {
let b = A;
let mut e = Example {
behaviours: Vec::new(),
};
e.add_behaviour(&b);
}
我明白了:
error[E0191]: the value of the associated type `Sub` (from trait `Behaviour`) must be specified
--> src/main.rs:17:29
|
3 | type Sub: SubBehaviour;
| ----------------------- `Sub` defined here
...
17 | behaviours: Vec<&'a dyn Behaviour>,
| ^^^^^^^^^ help: specify the associated type: `Behaviour<Sub = Type>`
为什么必须指定这种类型,特别是在我们只存储对对象的引用的情况下?我怎样才能让这个代码工作?
Why must this type must be specified, particularly in this case where we are only storing a reference to the object? How can I get this code to work?
推荐答案
所有类型在编译时都必须是静态已知的.如果 Rust 允许 Vec
的元素具有不同的关联类型,则类型信息可能取决于仅在运行时已知的索引.
All types must be statically known at compile time. If Rust would allow different associated types for elements of a Vec
, type information could depend on indices which are only known at runtime.
我发现考虑一个较小的例子会很有帮助:
I find it helpful to consider a smaller example:
trait Behaviour {
type T;
fn make_t(&self) -> T;
}
fn foo(my_vec: Vec<&dyn Behaviour>, index: usize) {
let t = my_vec[index].make_t(); //Type of t depends on index
}
不过,您的解决方法是正确的.我假设您引入了 SubBehaviour
特性,因为您意识到您需要对 T
可以是什么进行限制.问题是,在那种情况下,您不再需要关联类型.
You were on the right track to fixing this though. I assume you introduced the SubBehaviour
trait because you realized you need to put restrictions of what T
can be. The thing is, in that case you don't need an associated type anymore.
trait SubBehaviour {}
trait Behaviour {
fn make_t(&self) -> Box<dyn SubBehaviour>;
fn ref_t(&self) -> &dyn SubBehaviour; // also fine
}
fn some_function(my_vec: Vec<&dyn Behaviour>, index: usize) {
let t1 = my_vec[index].make_t();
}
唯一的限制是,在您对 Behaviour
的定义中,您不能做任何取决于 T
大小的事情(例如在堆栈上分配它或移动it) 因为 T
的大小不能由 SubBehaviour
trait 指定.
The only limitation is that in your definition of Behaviour
you can not do anything which would depend on the size of T
, (like allocating it on the stack or moving it) since the size of T
can not be specified by the SubBehaviour
trait.
这篇关于为什么必须在特征对象引用的集合中指定关联类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!