1. ホーム
  2. types

[解決済み] 汎用型と関連型の使い分けはいつが適切ですか?

2022-04-28 19:09:25

質問

この質問 一般的な型のパラメータを使おうとしていたのを、関連する型に変更することで解決できる問題が発生したのです。そのため、「なぜ、ここでは関連型がより適切なのか?

その 連想型を導入した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パラメータを使うことによる柔軟性の利点が明白でない場合には、関連する型から始めることをお勧めします。