Borrow 和 AsRef

2018-08-12 22:03 更新

Borrow 和 AsRef

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

Borrow

Borrow 特性是當你寫一個數(shù)據(jù)結構時,并且你想要使用一個 owned 或 borrowed 類型作為用于某些目的的同義詞。

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

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

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

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

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

use std::collections::HashMap:

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

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

這是因為標準庫中已經(jīng)為 String 類型實現(xiàn)了 Borrow 接口。

對于大多數(shù)類型,當你想要一個使用 owned 或者 borrowed 類型,使用 &T 就足夠了。但在不止一種 borrowed 值時,Borrow 處理起來是很高效的。Slice 指的是一塊區(qū)域:既可以是 &[T]也可以是 &mut[t] 類型。如果我們想使該區(qū)域同時存在著兩種類型,就可以使用 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);

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

AsRef

AsRef 是轉換特征。它被用在通用的代碼中將一些值轉換成索引類型。比如:

let s = "Hello".to_string();

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

應該用哪一個?

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

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

當你想要直接轉換某些類型為引用類型,并且你在編寫泛型時,你應該選擇 AsRef。

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號