pub trait AsRef<T: ?Sized> {
// Required method
fn as_ref(&self) -> &T;
}
Expand description
用于执行廉价的引用到引用转换。
一个类似于 AsMut
的 trait,用于在可变引用之间进行转换。
如果您需要进行代价高昂的转换,最好用 &T
类型实现 From
,或者编写一个自定义函数。
与 Borrow
的关系
AsRef
与 Borrow
具有相同的签名,但 Borrow
在以下几个方面有所不同:
- 与
AsRef
不同,Borrow
对任何T
都有一个毯子暗示,可用于接受引用或值。(另请参见下面关于AsRef
的反射性的注释。) Borrow
还要求借用值的Hash
、Eq
和Ord
与拥有值的值相等。因此,如果只想借用一个结构体的单个字段,则可以实现AsRef
,而不能实现Borrow
。
注意:此 trait 一定不能失败。如果转换失败,请使用专用方法返回 Option<T>
或 Result<T, E>
。
泛型实现
AsRef
自动引用,如果内部类型是一个引用或一个,可变引用 (例如: 如果 foo
具有 &mut Foo
或 &&mut Foo
类型,foo.as_ref()
将同样工作)。
请注意,由于历史原因,上述内容目前并不适用于所有 dereferenceable types,例如 foo.as_ref()
不会与 Box::new(foo).as_ref()
一样工作。
相反,许多智能指针提供了一个 as_ref
实现,它简单地将一个引用返回给 pointed-to value (但不对该值执行廉价的引用 - 到 - 引用转换)。
但是,AsRef::as_ref
不应仅用于解引用; 可以使用 ‘Deref
coercion’ 代替:
let x = Box::new(5i32);
// 避免这种情况:
// let y: &i32 = x.as_ref();
// 最好只写:
let y: &i32 = &x;
Run实现 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()
}
}
RunReflexivity
理想情况下,AsRef
将是自反的,即有一个 impl<T: ?Sized> AsRef<T> for T
与 as_ref
简单地返回其参数不变。
由于 Rust 类型系统的技术限制,目前不提供这样的一揽子实现 (它将与 &T where T: AsRef<U>
的另一个现有一揽子实现重叠,它允许 AsRef
自动解引用,请参见上面的 “Generic Implementations”)。
必须在需要或需要的地方为特定类型 T
显式添加 AsRef<T> for T
的简单实现。但是请注意,并非 std
中的所有类型都包含这样的实现,并且由于孤儿规则,这些类型不能由外部代码添加。
Examples
通过使用 trait bounds,我们可以接受不同类型的参数,只要它们可以转换为指定的 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);
Run