为什么必须在特征对象引用的集合中指定关联类型? [英] Why must the associated type be specified in a collection of trait object references?

查看:34
本文介绍了为什么必须在特征对象引用的集合中指定关联类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个令人反感的示例(游乐场):

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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆