[解決済み] 汎用型と関連型の使い分けはいつが適切ですか?
質問
で この質問 一般的な型のパラメータを使おうとしていたのを、関連する型に変更することで解決できる問題が発生したのです。そのため、「なぜ、ここでは関連型がより適切なのか?
その 連想型を導入したRFC は言う。
このRFCは、以下の方法でtrait matchingを明確にしています。
- すべての特性型パラメータを 入力タイプ であり、かつ
- 関連する型を提供することである。 出力タイプ .
このRFCでは、動機付けの例としてグラフ構造を用いており、これは、次のようなものである。
ドキュメント
しかし、私は、型パラメータ化されたバージョンよりも、関連付けられた型のバージョンの利点を十分に理解していないことを認めます。その第一は
distance
を気にする必要はありません。
Edge
という型があります。これは素晴らしいことですが、関連する型を持つ理由としては少し浅いように思えます。
実際に使ってみると、かなり直感的に使えることがわかるのですが、自分のAPIでいつどこで使うべきかを決めるときには苦労します。
コードを書くとき、どのような場合に汎用型パラメータではなく、関連型を選ぶべきでしょうか、また、どのような場合にその逆を選ぶべきでしょうか。
どのように解決する?
で触れられるようになりました。 の第2版です。 Rust プログラミング言語 . しかし、追加で少し飛び込んでみましょう。
まずは、もっと簡単な例から見ていきましょう。
どのような場合に特質法を使うのが適切なのでしょうか?
を提供する方法は複数あります。 レイトバインディング :
trait MyTrait {
fn hello_word(&self) -> String;
}
または
struct MyTrait<T> {
t: T,
hello_world: fn(&T) -> String,
}
impl<T> MyTrait<T> {
fn new(t: T, hello_world: fn(&T) -> String) -> MyTrait<T>;
fn hello_world(&self) -> String {
(self.hello_world)(self.t)
}
}
どのような実装/性能戦略であっても、上記の両方の抜粋により、ユーザーは動的な方法で、どのように
hello_world
の動作が必要です。
1つだけ(意味的に)違うのは
trait
の実装は、与えられた型に対して
T
を実装しています。
trait
,
hello_world
は常に同じ動作をするのに対し
struct
の実装では、インスタンスごとに異なる動作をさせることができます。
メソッドを使うことが適切かどうかは、ユースケースに依存します
<ブロッククオート関連する型を使用するのが適切なのはどんな場合か?
と同様に
trait
メソッドで、関連付けられた型はレイトバインディングの一種であり(コンパイル時に発生しますが)、これにより
trait
は、与えられたインスタンスに対して、どの型を代用するかを指定します。唯一の方法ではないのです(だから質問したのです)。
trait MyTrait {
type Return;
fn hello_world(&self) -> Self::Return;
}
または
trait MyTrait<Return> {
fn hello_world(&Self) -> Return;
}
は、上記のメソッドのレイトバインディングと同等です。
-
最初のものは、与えられた
Self
は1つのReturn
関連する -
を実装することができます。
MyTrait
に対してSelf
複数のReturn
どちらの形式が適切かは、一意性を強制することに意味があるかどうかで決まります。例えば
-
Deref
は関連する型を使用します。これは一意性がないと推論時にコンパイラが狂ってしまうからです。 -
Add
が連想型を使用しているのは、作者が 2 つの引数があれば論理的な戻り値の型が存在すると考えたからです。
ご覧のように
Deref
は明らかなユースケース(技術的制約)であるのに対し
Add
はあまり明確ではありません。
i32 + i32
のどちらかを返すようにします。
i32
または
Complex<i32>
文脈に応じて?それでも、作者は判断し、加算のための戻り値の型をオーバーロードする必要はないと判断した。
個人的なスタンスとしては、正解はないと思っています。ただ、一意性の議論を超えて、関連する型は指定しなければならないパラメータの数を減らすのでtraitの使用が容易になることを述べておきます。したがって、通常のtraitパラメータを使うことによる柔軟性の利点が明白でない場合には、関連する型から始めることをお勧めします。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン