Deref<Target = T>
, AsRef<T>
, Borrow<T>
和From<T> trait
差异这些trait
的共同作用就是“类型转换”,但它们“类型转换”的内容各有不同:
Deref<Target = T> / DerefMut<Target = T> trait
— 从一个类型的引用&F
至另一个类型的引用&T
的类型转换。Deref / DerefMut
仅能被同一个类型至多实现一次。所以,任何类型仅能作为另一个类型(而不是多个类型)的智能指针。AsRef<T> / AsMut<T> trait
— 从一个类型F
至另一个类型的引用&T
的类型转换Deref / DerefMut
,AsRef / AsMut
可以被同一个类型实现多次,且每次都指定不同的【泛型·类型实参】。所以,若抛开【智能指针】的语义,任何类型都能作为另外多个类型的引用。Borrow<T> / BorrowMut<T> trait
— 是AsRef<T> / AsMut<T> trait
的加强版本。F
·至·引用&T
·的类型转换,它还要求【类型转换·源类型】与【类型转换·目标类型】以一致的“行为”实现Eq
,Hash
与Ord
三个trait
。这样【源·类型】与【目标·类型】就备有相同的【判等·标准】。From<T> trait
— 从一个类型T
至另一个类型F
的类型转换。pub
数据,构造一个崭新的【类型转换·目标类型】实例trait
?总结起来,有两类套路:
Deref<Target = T> / DerefMut<Target = T> trait
AsRef<T> / AsMut<T> trait
Borrow<T> / BorrowMut<T> trait
trait
被实现于【类型转换·源类型】trait
成员方法取得【目标·类型】的引用。trait
包括From<T> trait
trait
被实现于【类型转换·目标类型】trait
包括trait
引导的【类型转换】?总结起来,也有两类套路:
rustc
会自动给类型F
实现Into<T> trait
。于是,就有<F, T> where T: From<F>, F: Into<T>
。其中,F: Into<T>
是被编译器“买一送一”的。F
可被显示地类型转换至T
[例程4],仅需要显示调用F
的trait
成员方法<F as Into>::into(_: F)
。F
就是T
的【智能指针】— 给普通【引用】赋能了·额外的自定义功能·和保存了·更多状态信息·&F
可被隐式地“类型转换”为&T
[例程3] — 不需要任何额外的编码,因为【自动·解引用】。&F
(而不是F
)是因为【解引用】必须以【引用&F
】为起点,而不是【所有权·变量F
】。<F, T> where F: Deref<Target = T>
,那么<F, T> where T: From<F>
,那么F
可被显示地“类型转换”为&T
[例程6],需要F
与&T
以一致的行为实现了Eq
,Hash
和Ord
三个trait
。即,若x.borrow() == y.borrow()
,就意味着x == y
。反之亦然。Borrow<T>
出现于【泛型·代码】内和作为【泛型·类型参数】的trait
限定条件。F
的成员方法<F as Borrow>::borow(_: &F)
。F
可被显示地“类型转换”为&T
[例程5],需要AsRef<T>
出现于【泛型·代码】内和作为【泛型·类型参数】的trait
限定条件。F
的trait
成员方法<F as AsRef>::as_ref(_: &F)
。<F, T> where F: AsRef<T>
,那么<F, T> where F: Borrow<T>
,那么trait
的常见使用场景模仿OOP
中的函数重载。即,让同一个函数
就是模仿得不是很彻底。
向HashMap<K, V>
添加新【键-值对】和从HashMap<K, V>
检索已有的【键-值对】。
HashMap<K, V>
需要拥有它的【集合·元素】std::collections::hash_map::Entry
的所有权。所以,HashMap::insert(_: K, _: V)
成员方法要求【键】与【值】的所有权·变量。HashMap<K, V>
查询检索过程中,对【键】数据的所有权要求就可以忽略了,因为这可以避免潜在的【堆】分配和提高程序性能。但是,为了确保搜索结果的一致性,【键】数据的
必须具备相同的【判等·标准】(即,行为一致的Eq trait
, Ord trait
与Hash trait
实现)。于是,若有<K, V> where K: Borrow<Q> + Eq + Hash, Q: Eq + Hash
(其中,K: Borrow<Q>
被读作:K
被借入作为Q
),那么由HashMap::get(_: &Q)
检索出来的【值】就是由对应的HashMap::insert(_: K, _: V)
添加的【值】。