web-dev-qa-db-ja.com

特性をオブジェクトにすることはできません

私は次のコードを持っています:

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

私はそれがなぜ起こるか知っていると思うが、どのように構造体から特性を参照するのですか?出来ますか?同じ動作を実装する他の方法がありますか?

16
Alexander

Zernike's answer のように、構造体に型パラメーターを追加するか、特性オブジェクトを使用できます。

Typeパラメーターを使用すると、Tの各値が構造体の特殊なコピーを作成するため、パフォーマンスが向上し、静的ディスパッチが可能になります。特性オブジェクトは動的ディスパッチを使用するため、実行時に具象型を交換できます。

特性オブジェクトのアプローチは次のようになります。

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

またはこれ:

pub struct MyStruct {
    my_trait: Box<dyn MyTrait>,
}

ただし、あなたの場合、MyStructは静的メソッドであるため、receiveをオブジェクトにすることはできません。 &selfまたは&mut selfを機能させるための最初の引数として。 その他の制限 もあります。

18
Peter Hall
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

6
Zernike

4番目のオプションがありますが、これにより構造体のサイズが変更されます。つまり、この構造体のインスタンスを作成することはできません。

pub trait MyTrait {}

pub struct MyStruct {
    my_trait: dyn MyTrait + 'static,
}

これは、MyStructがサイズ変更されていないタイプであり、そのようなタイプの直接インスタンスを作成できないことを意味します。 Rustは現在、スタックに直接構造体を割り当てる方法がないため、このような型のインスタンスを作成できるかどうかはまったくわかりません。しかし、ちょっと、 itコンパイル

0
Hauleth