Borrow 和 AsRef

2018-08-12 22:03 更新

Borrow 和 AsRef

BorrowAsRef 特性是非常相似的,但是也有些區(qū)別。這里有一個(gè)簡(jiǎn)單回顧一下這兩個(gè)特質(zhì)是什么意思。

Borrow

Borrow 特性是當(dāng)你寫(xiě)一個(gè)數(shù)據(jù)結(jié)構(gòu)時(shí),并且你想要使用一個(gè) owned 或 borrowed 類(lèi)型作為用于某些目的的同義詞。

例如,HashMap 的 get 方法就使用了 Borrow:

 fn get<Q: ?Size>(&self, k:&Q) -> Option<&V>
    where K:Borrow<Q>,
          Q:Hash +Eq

這個(gè)簽名是相當(dāng)復(fù)雜的。在這里我們感興趣的是 K 參數(shù)。它指的是 HashMap 本身的一個(gè)參數(shù):

struct HashMap<K, V, S = RandomState> {

K 參數(shù)是 HashMap 中使用的 key 類(lèi)型。所以,再次看 get() 函數(shù)簽名,當(dāng) key 實(shí)現(xiàn)了 Borrow 時(shí)我們可以使用 get() 函數(shù)。這樣,我們可以使用 String 類(lèi)型作為 HashMap 的 key,而使用 &strs 進(jìn)行搜索:

use std::collections::HashMap:

let mut map = HashMap::new();
map.insert("Foo".to_string(), 42);

assert_eq!(map.get("Foo"), Some(&42));

這是因?yàn)闃?biāo)準(zhǔn)庫(kù)中已經(jīng)為 String 類(lèi)型實(shí)現(xiàn)了 Borrow 接口。

對(duì)于大多數(shù)類(lèi)型,當(dāng)你想要一個(gè)使用 owned 或者 borrowed 類(lèi)型,使用 &T 就足夠了。但在不止一種 borrowed 值時(shí),Borrow 處理起來(lái)是很高效的。Slice 指的是一塊區(qū)域:既可以是 &[T]也可以是 &mut[t] 類(lèi)型。如果我們想使該區(qū)域同時(shí)存在著兩種類(lèi)型,就可以使用 Borrow:

use std::borrow::Borrow;
use std::fmt::Display;

fn foo<T: Borrow<i32> + Display>(a: T) {
    println!("a is borrowed: {}", a);
}

let mut i = 5;

foo(&i);
foo(&mut i);

上面的代碼會(huì)輸出 a is borrowed: 5 兩次。

AsRef

AsRef 是轉(zhuǎn)換特征。它被用在通用的代碼中將一些值轉(zhuǎn)換成索引類(lèi)型。比如:

let s = "Hello".to_string();

fn foo<T: AsRef<str>>(s: T) {
    let slice = s.as_ref();
}

應(yīng)該用哪一個(gè)?

我們可以看到他們是如何的相似:他們都處理 owned 和 borrowed 版本的數(shù)據(jù)類(lèi)型。然而,他們還是有點(diǎn)不同。

當(dāng)你想要抽象出各種 borrowing 數(shù)據(jù)中的不同,或者你創(chuàng)建的數(shù)據(jù)結(jié)構(gòu)用同樣的方式對(duì)待 owned 和 borrowed 值,比如哈希操作和比較操作,此時(shí)你應(yīng)該選擇 Borrow。

當(dāng)你想要直接轉(zhuǎn)換某些類(lèi)型為引用類(lèi)型,并且你在編寫(xiě)泛型時(shí),你應(yīng)該選擇 AsRef。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)