トレイト AsRef
Since 1.0.0 (const: unstable) · Sourcepub trait AsRef<T>where T: ?Sized, { // Required method fn as_ref(&self) -> &T; }説明を展開
参照から参照への安価な変換に使用される。
このトレイトは可変参照との変換に使われる
AsMutと似ている。もしも高コストな変換を行う必要があるのなら&TにFromを実装するか自作の関数を書こう。
Borrowとの関係
AsRefはBorrowと同じシグネチャを持つが、Borrowとは幾つかの点で異なる。
AsRefとは違い、Borrowは任意のTに対するブランケット実装を持つため、参照と値の双方を受けいれるのに使える (下記のAsRefの反射性の但し書きを見よ)。- また
Borrowは借用される値のHash,EqそしてOrdが所有される値のそれと同じになる事を要求する。この理由のため、構造体の単一のフィールドのみを借用したいのなら、AsRefでの実装はできるがBorrowではできない。Note: このトレイトは失敗してはならない。もし変換が失敗しうるなら、
Option<T>やResult<T, E>を戻す専用のメソッドを使え。一般的な実装
AsRefはもし内部の型が参照や可変参照なら自動逆参照する (例:foo.as_ref()はfooが&mut Fooや&&mut Fooなら同じ働きをする)。なお歴史的経緯のため現在、上記は全ての逆参照可能型で一般化されているわけではなく、例えば
foo.as_ref()はBox::new(foo).as_ref()と同じ働きとはならない。代わりに、多くのスマートポインタは単純にポイントされた値への参照を戻すだけのas_refの実装を提供する (逆にその値には参照から参照への低コストな変換は実施されない)。とは言え、AsRef::as_refを逆参照だけの目的で使うべきではない; 代わりに ‘Deref強制’ が使用できる:let x = Box::new(5i32); // これは避けて: // let y: &i32 = x.as_ref(); // こう書くだけで良い: let y: &i32 = &x;
Derefを実装する型はAsRef<T>を以下のように実装するよう考慮すべきである:impl<T> AsRef<T> for SomeType where T: ?Sized, <SomeType as Deref>::Target: AsRef<T>, { fn as_ref(&self) -> &T { self.deref().as_ref() } }反射性
理想的には、
AsRefは反射的であるべきで、つまりimpl<T: ?Sized> AsRef<T> for Tはas_refで単純にその引数を変更せずに戻すべきである。だが Rust の型システムの技術的制約のためそのようなブランケット実装は現在は提供されていない (それが既存のブランケット実装の&T where T: AsRef<U>と重複するためで、これは上記の『一般的な実装』の通り、AsRefに自動逆参照を可能にしている)。特定の型
TのためのAsRef<T> for Tの素朴な実装が必要または期待されるなら明示的な追加が必要になる。しかしながら、std由来の全ての型にそうした実装が含まれているわけではなく、またそれらは孤児ルールにより外部コードから追加できない事に注意せよ。例
トレイト境界を使用する事で異なる型の引数をそれらが特定の型
Tに変換できる限り受け入れられる。例えば:
AsRef<str>をとるジェネリック関数を作成する事で、&strに変換できる全ての参照を受け入れたい事を表現できる。Stringと&strは共にAsRef<str>を実装しているので共に入力引数として受け入れできる。fn is_hello<T: AsRef<str>>(s: T) { assert_eq!("hello", s.as_ref()); } let s = "hello"; is_hello(s); let s = "hello".to_string(); is_hello(s);要求されるメソッド
1.0.0 · Source
fn as_ref(&self) -> &Tこの型を入力型 (通常は推論される) の共有参照へと変換する。