Foo
を実装するものを格納できる型は宣言していません。 Foo
を実装する型の特定のオブジェクトを格納できる型を作成するための一種のファクトリを宣言しました。
struct Abc<F: Foo> {
f: F
}
これは、「私にFoo
を実装タイプF
を与える、と私は1つ格納タイプAbc<F>
作成します」をとほぼ翻訳:あなたのコードの一部を通って行く
。
あなたがそれを使用します。
let mut abc = Abc { f: Box::new(Zxc) };
コンパイラによって推論種類に戻って追加:
let mut abc: Abc<Zxc> = Abc { f: Box::new(Zxc) };
のでabc.f
のタイプはBox<Zxc>
ある - ないBox<Foo>
。
だから今はAbc<Zxc>
を持っている - (あなたがタイプパラメータF
を指定するまで、あなたは具体的なオブジェクトを作成することはできません)Abc
汎用的ではありません。
Baz
と一緒に使用できない理由は明らかです。さて、実際のエラーになって
:エラーがabc.bared
への呼び出しには、実際にはない
<anon>:17:18: 17:19 error: mismatched types: expected `F`,
found `B` (expected type parameter,
found a different type parameter) [E0308] <anon>:17 self.f = b;
^<anon>:17:18: 17:19 help: see the detailed explanation for E0308 error: aborting due to previous error
。
// In the impl of Abc<F>
fn bared<B: Bar + 'static>(&mut self, b: B) {
self.f = Box::new(b);
}
この方法は、それがBar
を実装していますが、全くF
に関連していなくてもよい任意の型B
を取ると言い、そしてself.f
に格納し、タイプBox<F>
である:それは定義です。をBox<F>
に割り当てることはできません。
@kennytmによれば、フィールドを特性オブジェクト(Box<Foo>
)にすることで、他の言語の基本クラスポインタに似ています。
impl<F: Foo> Abc<F> {
fn bared<B: Bar>(self, b: B) -> Abc<B> {
Abc { f: b }
}
}
この:あなたはBuilderパターンを構築しようとしている場合は他の回答に加えて
たぶん 'unsafe'を使用してのようなもの? – Lupe
ここで 'unsafe'を使わないことを100%推奨します。私はそれが必要だとは思わないし、それを使用するとメモリエラーにつながる可能性が高い。 – Shepmaster
良いAPIを作成するための@Shepmaster Crutch – Lupe