特质不能变成对象

Posted

技术标签:

【中文标题】特质不能变成对象【英文标题】:The trait cannot be made into an object 【发布时间】:2017-07-15 10:09:34 【问题描述】:

我有以下代码:

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,

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

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

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

【问题讨论】:

【参考方案1】:

您可以向结构添加类型参数,如Zernike's answer,或使用特征对象。

使用类型参数会更好地提高性能,因为T 的每个值都会创建结构的专用副本,从而允许静态分派。 trait 对象使用动态调度,因此它允许您在运行时交换具体类型。

特征对象方法如下所示:

pub struct MyStruct<'a> 
    my_trait: &'a dyn MyTrait,

或者这个:

pub struct MyStruct 
    my_trait: Box<dyn MyTrait>,

但是,在您的情况下,MyStruct 不能成为对象,因为receive 是静态方法。您需要将其更改为将 &amp;self&amp;mut self 作为其第一个参数才能使其正常工作。还有other restrictions。

【讨论】:

【参考方案2】:
pub struct MyStruct<T>
where
    T: MyTrait,

    my_trait: T,

pub struct MyStruct<T: MyTrait> 
    my_trait: T,

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

【讨论】:

我不喜欢这种变体,因为以后我不能用另一个实例替换 T。【参考方案3】:

还有第四个选项可用,但这会使您的结构变小,也就是您将无法创建此结构的实例。

pub trait MyTrait 

pub struct MyStruct 
    my_trait: dyn MyTrait + 'static,

这意味着MyStruct 是一个无大小的类型,您不能直接创建这种类型的实例。由于 Rust 目前没有办法直接在堆栈上分配结构,我不知道你是否可以创建这种类型的实例。但是,嘿,it compiles。

【讨论】:

How do you actually use dynamically sized types in Rust?. @Shepmaster 我知道如何使用未调整大小的类型。但我找不到实例化这种特定类型的方法。我知道如何使用像 struct Foo(str) 这样的类型,但我找不到使用这种类型的方法。 我同意你目前不能这样做。该链接适用于当有人在 X 个月内偶然发现此答案时,只要可以更轻松地使用 DST。该问答将使用新信息进行更新;这个不太可能。

以上是关于特质不能变成对象的主要内容,如果未能解决你的问题,请参考以下文章

Scala语法详解:特质 (Traits)

Scala学习三-面向对象

scala——关键字trait的使用

Scala入门2(特质与叠加在一起的特质)

如何从盒装特质创建特质对象?

Scala 面向对象:package 包