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

關(guān)聯(lián)類型

關(guān)聯(lián)類型是 Rust 的類型系統(tǒng)一個(gè)強(qiáng)大的部分。它們與一個(gè)“類型家族”的概念有關(guān),換句話說,就是將多種類型組合在一起。這樣描述有點(diǎn)抽象,所以讓我們深入理解一個(gè)例子。如果你想寫一個(gè)特征,名字為 Graph ,你有2種類型是通用的:節(jié)點(diǎn)類型和邊類型。所以你可以寫一個(gè)特征 ,Graph<N, E>,看起來(lái)像這樣:

trait Graph<N, E> {
fn has_edge(&self, &N, &N) -> bool;
fn edges(&self, &N) -> Vec<E>;
// etc
}

但是這類代碼結(jié)束的不太合適。例如,任何想要以 Graph 為參數(shù)的函數(shù),現(xiàn)在也需要在節(jié)點(diǎn)和邊類型上是通用的:

fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }

我們的距離計(jì)算與我們的類型 Edge 無(wú)關(guān),所以填充在聲明中的 E 只是一個(gè)無(wú)關(guān)變量。

我們真正想說的是,邊 Edge 和 Node 類型一起構(gòu)成 Graph 類。我們可以稱它們?yōu)殛P(guān)聯(lián)類型:

trait Graph {
type N;
type E;

fn has_edge(&self, &Self::N, &Self::N) -> bool;
fn edges(&self, &Self::N) -> Vec<Self::E>;
// etc
}

現(xiàn)在,我們的客戶端可以抽象出一個(gè)給定的 Graph:

fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }

這里不需要處理 Edge 類型!

讓我們更詳細(xì)地去學(xué)習(xí)這些知識(shí)。

定義關(guān)聯(lián)類型

讓我們構(gòu)建特征 Graph。這里是它的定義:

trait Graph {
type N;
type E;

fn has_edge(&self, &Self::N, &Self::N) -> bool;
fn edges(&self, &Self::N) -> Vec<Self::E>;
}

這很簡(jiǎn)單。關(guān)聯(lián)類型要在特征函數(shù)體內(nèi)使用 type 關(guān)鍵字?!   ?/p>

這些 type 聲明可以有和函數(shù)一樣的功能。例如,如果我們希望我們的 N 類型實(shí)現(xiàn) Display,所以我們可以打印節(jié)點(diǎn),我們可以這樣做:

use std::fmt;

trait Graph {
type N: fmt::Display;
type E;

fn has_edge(&self, &Self::N, &Self::N) -> bool;
fn edges(&self, &Self::N) -> Vec<Self::E>;
}

關(guān)聯(lián)類型的實(shí)現(xiàn)

就像任何特征,使用關(guān)聯(lián)類型的特征要使用 impl 關(guān)鍵字提供實(shí)現(xiàn)。這是一個(gè)Graph 的簡(jiǎn)單實(shí)現(xiàn):

struct Node;

struct Edge;

struct MyGraph;

impl Graph for MyGraph {
type N = Node;
type E = Edge;

fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
true
}

fn edges(&self, n: &Node) -> Vec<Edge> {
Vec::new()
}
}

這個(gè)簡(jiǎn)單的實(shí)現(xiàn)總是返回 true 和一個(gè)空的 Vec <Edge>,但它給了你一個(gè)如何實(shí)現(xiàn)這種功能的辦法。我們首先需要三個(gè)struct,一個(gè)圖,一個(gè)節(jié)點(diǎn),一個(gè)邊。如果使用不同的類型,那也行,我們只是要用所有這三個(gè)變量的 struct。    

接下來(lái)是 impl,它就像實(shí)現(xiàn)任何其他特征一樣?!   ?/p>

在這里,我們使用 = 定義我們的關(guān)聯(lián)類型。特征使用的名字放在 = 的左側(cè),我們實(shí)現(xiàn)的具體類型放在 = 右邊。最后,我們使用函數(shù)中聲明的具體類型。

關(guān)聯(lián)類型的特征對(duì)象

還有一個(gè)語(yǔ)法我們應(yīng)該談?wù)撘幌拢禾卣鲗?duì)象。如果你想創(chuàng)建一個(gè)關(guān)聯(lián)類型的特征對(duì)象,如下:

let graph = MyGraph;
let obj = Box::new(graph) as Box<Graph>;

你會(huì)得到兩個(gè)錯(cuò)誤:

error: the value of the associated type `E` (from the trait `main::Graph`) must
be specified [E0191]
let obj = Box::new(graph) as Box<Graph>;

24:44 error: the value of the associated type `N` (from the trait
`main::Graph`) must be specified [E0191]
let obj = Box::new(graph) as Box<Graph>;

我們不能像這樣創(chuàng)建一個(gè)特征對(duì)象,因?yàn)槲覀儾恢狸P(guān)聯(lián)類型。相反,我們可以寫:

let graph = MyGraph;
let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;

N=Node 語(yǔ)法允許我們?yōu)?N 類型參數(shù)提供一個(gè)具體的類型,Node。E=Edge 也一樣。如果我們沒有提供這個(gè)約束,我們無(wú)法確定哪一個(gè) impl 與這個(gè)特征對(duì)象相匹配。