鍍金池/ 教程/ Java/ 'Deref'強(qiáng)制轉(zhuǎn)換
While 循環(huán)
宏命令
模式
Rust 嵌入到其他語言
變量綁定
if
發(fā)布通道
Lang 項(xiàng)目
匹配
文檔
棧和堆
不依賴 stdlib
原始指針
條件編譯
type 別名
關(guān)聯(lián)類型
全類型
詞匯表
基本類型
Hello, world!
測試
箱和模塊
字符串
向量
引用與借用
所有權(quán)
內(nèi)斂函數(shù)
基準(zhǔn)測試
Nightly Rust
for 循環(huán)
特征
特征的對象
鏈接參數(shù)
介紹
'Deref'強(qiáng)制轉(zhuǎn)換
枚舉
內(nèi)聯(lián)匯編
泛型
方法語法
函數(shù)
外部函數(shù)接口
盒語法和模式
安裝 Rust
unsafe    
生存期
切片模式
Borrow 和 AsRef
If let
學(xué)習(xí) Rust
“常量”和“靜態(tài)”
語法和語義
迭代器
相關(guān)學(xué)術(shù)研究
通用函數(shù)調(diào)用語法
哲學(xué)家就餐問題
類型轉(zhuǎn)換
閉包
并發(fā)性
Hello, Cargo!
屬性
注釋
結(jié)構(gòu)體
編譯器插件
高效 Rust
相關(guān)常量
猜謎游戲
可變性
錯(cuò)誤處理
新手入門
操作符和重載

'Deref'強(qiáng)制轉(zhuǎn)換

標(biāo)準(zhǔn)庫提供了一個(gè)特殊的特征,Deref。它通常用于重載 * ,取消引用運(yùn)算符:

use std::ops::Deref;

struct DerefExample<T> {
value: T,
}

impl<T> Deref for DerefExample<T> {
type Target = T;

fn deref(&self) -> &T {
&self.value
}
}

fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x);
}

這用于編寫自定義指針類型。然而,有一個(gè)與 Deref 相關(guān)的語言特征:‘deref 強(qiáng)制轉(zhuǎn)換’。規(guī)則是這樣的:如果你有一個(gè)類型 U,它實(shí)現(xiàn) Deref<Target=T>,&U 的值自動強(qiáng)制轉(zhuǎn)換為 &T。這里有一個(gè)例子:

fn foo(s: &str) {
// borrow a string for a second
}

// String implements Deref<Target=str>
let owned = "Hello".to_string();

// therefore, this works:
foo(&owned);

在一個(gè)值前使用 & 需要一個(gè)引用。所以 owned 是一個(gè) String,&owned 是一個(gè) &String,并且由于 impl Deref<Target=str> for String,&String 參考傳入函數(shù) foo() 的 &str。

就這樣。這條規(guī)則是 Rust 為你自動轉(zhuǎn)換的少有的幾處之一,但它增加了很大的靈活性。例如,類型 Rc<T> 實(shí)現(xiàn) Deref<Target=T>,所以它的工作原理如下:

use std::rc::Rc;

fn foo(s: &str) {
// borrow a string for a second
}

// String implements Deref<Target=str>
let owned = "Hello".to_string();
let counted = Rc::new(owned);

// therefore, this works:
foo(&counted);

所有我們所做的就是把我們的 String 封裝到 Rc<T>。但是我們現(xiàn)在可以把 Rc<String> 傳到任何有 String 的地方。foo 的聲明并沒有改變,但能實(shí)現(xiàn)與其它類型一樣的功能。這個(gè)例子有兩個(gè)轉(zhuǎn)換:Rc<String> 轉(zhuǎn)換為 String,然后 String 轉(zhuǎn)換為 &str。Rust 會這樣做盡可能多的次數(shù)直到類型匹配?!   ?/p>

標(biāo)準(zhǔn)庫提供的另一個(gè)很常見的實(shí)現(xiàn)是:

fn foo(s: &[i32]) {
// borrow a slice for a second
}

// Vec<T> implements Deref<Target=[T]>
let owned = vec![1, 2, 3];

foo(&owned);

向量可以取消對程序片的引用。

Deref 和方法調(diào)用

Deref 調(diào)用方法時(shí)也起作用。換句話說,Rust 有相同的兩件事:

struct Foo;

impl Foo {
fn foo(&self) { println!("Foo"); }
}

let f = Foo;

f.foo();

盡管 f 不是引用,但是函數(shù) foo 中傳入 &self 就會起作用。這是因?yàn)檫@些東西是相同的:

f.foo();
(&f).foo();
(&&f).foo();
(&&&&&&&&f).foo();

&&&&&&&&&&&&&&&&Foo 類型的值仍然可以有定義在 Foo 上的方法,因?yàn)榫幾g器會插入許多 操作只要程序正確運(yùn)行。因?yàn)樗牟迦?/em> s,就要使用 Deref。

上一篇:Borrow 和 AsRef下一篇:測試