コレクションはスマートポインタ
説明
Deref トレイトを使用して、コレクションをスマートポインタのように扱い、データの所有ビューと借用ビューを提供します。
例
use std::ops::Deref;
struct Vec<T> {
data: RawVec<T>,
//..
}
impl<T> Deref for Vec<T> {
type Target = [T];
fn deref(&self) -> &[T] {
//..
}
}
Vec<T> は T の所有コレクションであり、スライス(&[T])は T の借用コレクションです。Vec に Deref を実装することで、&Vec<T> から &[T] への暗黙的な参照外しが可能になり、自動参照外し検索に関係性が含まれます。Vec に実装されていると予想されるほとんどのメソッドは、代わりにスライスに実装されています。
また、String と &str も同様の関係を持っています。
動機
所有権と借用は Rust 言語の重要な側面です。データ構造は、良好なユーザーエクスペリエンスを提供するために、これらのセマンティクスを適切に考慮する必要があります。データを所有するデータ構造を実装する際、そのデータの借用ビューを提供することで、より柔軟な API が可能になります。
利点
ほとんどのメソッドは借用ビューに対してのみ実装でき、その後暗黙的に所有ビューでも利用可能になります。
クライアントにデータの借用または所有権の取得の選択肢を提供します。
欠点
参照外しを介してのみ利用可能なメソッドとトレイトは、境界チェック時に考慮されないため、このパターンを使用するデータ構造でのジェネリックプログラミングは複雑になる可能性があります(Borrow や AsRef トレイトなどを参照)。
議論
スマートポインタとコレクションは類似しています。スマートポインタは単一のオブジェクトを指し、コレクションは多数のオブジェクトを指します。型システムの観点からは、両者にほとんど違いはありません。コレクションが各データにアクセスする唯一の方法がコレクションを介する場合、およびコレクションがデータの削除に責任を持つ場合(共有所有権の場合でも、何らかの借用ビューが適切である場合があります)、コレクションはそのデータを所有します。コレクションがデータを所有する場合、通常、データの借用ビューを提供して複数回参照できるようにすることが有用です。
ほとんどのスマートポインタ(例:Foo<T>)は Deref<Target=T> を実装します。ただし、コレクションは通常、カスタム型に参照外しされます。[T] と str には言語サポートがありますが、一般的なケースでは必要ありません。Foo<T> は Deref<Target=Bar<T>> を実装でき、ここで Bar は動的サイズ型であり、&Bar<T> は Foo<T> のデータの借用ビューです。
一般的に、順序付きコレクションは Range に対して Index を実装し、スライス構文を提供します。ターゲットは借用ビューになります。