特征不能成为一个对象

Ale*_*der 17 generics traits dynamic-dispatch rust trait-objects

我有以下代码:

extern crate futures; // 0.1.24

use futures::Future;
use std::io;

struct Context;

pub trait MyTrait {
    fn receive(context: Context) -> Future<Item = (), Error = io::Error>;
}

pub struct MyStruct {
    my_trait: MyTrait,
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译它时,我收到错误消息:

error[E0038]: the trait `MyTrait` cannot be made into an object
  --> src/lib.rs:13:5
   |
13 |     my_trait: MyTrait,
   |     ^^^^^^^^^^^^^^^^^ the trait `MyTrait` cannot be made into an object
   |
   = note: method `receive` has no receiver
Run Code Online (Sandbox Code Playgroud)

我想我知道它为什么会发生,但我如何从结构中引用特征呢?可能吗?也许还有其他方法可以实现相同的行为?

Pet*_*all 19

您可以在结构中添加类型参数,如Zernike的答案,或使用特征对象.

使用type参数对性能更好,因为每个值都T将创建struct的专用副本,允许静态分派.特征对象使用动态分派,因此它允许您在运行时交换具体类型.

特征对象方法如下所示:

pub struct MyStruct<'a> {
    my_trait: &'a dyn MyTrait,
}
Run Code Online (Sandbox Code Playgroud)

或这个:

pub struct MyStruct {
    my_trait: Box<dyn MyTrait>,
}
Run Code Online (Sandbox Code Playgroud)

但是,在您的情况下,MyStruct因为receive是静态方法而无法成为对象.你需要改变它,&self或者&mut self作为它的第一个参数.还有其他限制.


Zer*_*ike 7

pub struct MyStruct<T>
where
    T: MyTrait,
{
    my_trait: T,
}
Run Code Online (Sandbox Code Playgroud)

要么

pub struct MyStruct<T: MyTrait> {
    my_trait: T,
}
Run Code Online (Sandbox Code Playgroud)

https://doc.rust-lang.org/book/second-edition/ch10-02-traits.html#trait-bounds

  • 我不喜欢这种变体,因为那样以后我就不能用另一个实例替代T了。 (2认同)