問題タブ [trait-objects]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
rust - Rustでボックス化された特性オブジェクトを値で渡す方法は?
私はいくつかのコードを書いていて、値を取るメソッドを持つ特性を持っていましたself
。Box
'd trait オブジェクトでこのメソッドを呼び出したい(Box
およびその値を消費する)。これは可能ですか?もしそうなら、どのように?
コードに関しては、最小限の例は次の (不完全な) コードのようになります。
私の質問は、指定された署名を関数に入力して、返される値が'd 値consume_box
を呼び出すことによって取得される値になるようにする方法です。consume
Box
最初に書いていた
関数の本体として、これはまったく正しい考えではないことはわかっていBox
ますが、その内容だけでなく、それを消費したいという事実を理解していないため、それが私が考えることができる唯一のものです. これはコンパイルされず、エラーが発生します。
タイプ dyn 消耗品の値を移動できません: dyn 消耗品のサイズは静的に決定できません
Rust を初めて使用する私にとって、これは少し驚きでした。self
引数が C++ の右辺値参照と同様に渡されるのではないかと考えていました (これは本当に私が望んでいることです。C++ では、おそらく署名付きのメソッドによってこれを実装するでしょう)。virtual std::uint64_t consume() &&
、std::unique_ptr
仮想デストラクタを介して移動元オブジェクトをクリーンアップできるようにします)が、Rustは本当に値渡しであり、引数を前の場所に移動していると思います-したがって、コードを拒否するのは合理的です.
Box
問題は、 'd 特性オブジェクトを消費できる場所で、必要な動作を取得する方法がわからないことです。デフォルトの実装でトレイトにメソッドを追加しようとしましたが、vtable で何か便利なものが得られるかもしれないと考えました。
ただし、これによりエラーが発生します
特性
Consumable
をオブジェクトにすることはできません
型について言及すると、Box<dyn Consumable>
これはそれほど驚くべきことではありません。引数の型が変化する関数をどう処理するかをコンパイラが判断するのSelf
は奇跡的だったからです。
提供された署名を使用して関数を実装することは可能consume_box
ですか?必要に応じて特性を変更することもできますか?
有用な場合、より具体的には、これはいくつかの数式の一種の表現の一部です。おもちゃのモデルは、大まかに次のような特定の実装になる可能性があります。
ここで、ほとんどの場合、物事は単純な古いデータです(ただし、ジェネリックのために、潜在的にその大きなブロックです)が、これをこれらの種類のものへのより不透明なハンドルを渡すことと互換性があるようにするため、欲求で作業できるようにしBox<dyn Consumable>
ます。少なくとも言語レベルでは、これは私がやっていることの良いモデルです - これらのオブジェクトが所有する唯一のリソースはメモリの断片です (マルチスレッドとは何の関係もありませんし、自己参照的な悪ふざけもありません) - これはモデルは、私が持っているユースケースが、単にオブジェクトを読み取るのではなく、実装がオブジェクトを消費するのに役立つものであることを把握しておらず、「オープン」が必要であることを適切にモデル化していませんenum
それはツリーを直接表します) - したがって、参照渡しに書き直そうとするのではなく、値渡しについて尋ねているのはなぜですか。
generics - Rcをキャストするにはどうすればよいですか> Rcへ>?
( implements )にキャストしようとしてRc<RefCell<Data>>
いますが、一般的なメソッドでは不可能です:Rc<RefCell<dyn Interface>>
Data
Interface
非プリミティブ キャストでコンパイル エラーが発生しました。
rust - Rustでバインドされた再帰的特性を定義するには?
Box
まず、再帰構造を定義したい場合に使用できることを知っています。例えば、
しかし、これらの構造にテンプレートまたは trait オブジェクトを介してどのように特徴を作成できますか? が存在するため、次のfn append_next(...) -> Self
ように特性オブジェクトを直接作成することはできません。
Option<Box<impl Linkable>>
また、またはimpl Linkable
の返品はできませんfn get_next(&self)
。
次に、汎用テンプレートを介して次の実装を試みましたが、機能しません。T
new を構築するときに の型を再帰的に割り当てる必要があるためですLinkNode
。
最終的には、支援のための他の特性を作成することで、この方法で実装します。そして、それはうまく機能します。もう一度...他に良い方法はありますか?
ところで、上記の調査中に他にもいくつか質問があります。なぜRustはimpl Linkable
砂糖を禁止するのBox<impl Linkale>
ですか? そして、なぜ復帰impl Linkable
が特性で禁止されているのですか?
Ibraheemの回答後に更新:
Ibraheemからの関連付けられた型の実装を除いて、このように動作することも問題ありません。コアとなるアイデアは、トレイトでの再帰的な型宣言を避けることです。