鍍金池/ 教程/ Java/ 特性
標準輸入與輸出
消息傳遞
循環(huán)
注釋
Rust for Mac OS
幾種智能指針
Cell, RefCell
trait對象 (trait object)
rust web 開發(fā)
Unsafe、原始指針
Macro
迭代器
函數(shù)
Borrow, BorrowMut, ToOwned
快速上手
二叉樹
編輯器
測試與評測
Deref
安裝Rust
哈希表 HashMap
原生類型
17.錯誤處理
VS Code 安裝配置
動態(tài)數(shù)組Vec
模式匹配
操作符和格式化字符串
Rust for Linux
函數(shù)參數(shù)
Visual Studio
vim/GVim安裝配置
閉包作為參數(shù)和返回值
安全(Safety)
Cow
生命周期( Lifetime )
閉包的實現(xiàn)
所有權(quán)(Ownership)
Atom
將Rust編譯成庫
類型、運算符和字符串
類型系統(tǒng)中的幾個常見 trait
特性
屬性和編譯器參數(shù)
Spacemacs
集合類型
Rust json處理
Heap & Stack
并行
標準庫示例
基本程序結(jié)構(gòu)
鏈表
trait 和 trait對象
前期準備
代碼風格
編譯器參數(shù)
基于語義化版本的項目版本聲明與管理
Rust 版本管理工具: rustup
引用&借用(References&Borrowing)
注釋與文檔
10.1 trait關(guān)鍵字
模式
調(diào)用ffi函數(shù)
unsafe
并發(fā),并行,多線程編程
AsRef 和 AsMut
Rust旅程
Rust for Windows
結(jié)構(gòu)體與枚舉
條件分支
附錄I-術(shù)語表
變量綁定與原生類型
Mutex 與 RwLock
泛型
裸指針
常用數(shù)據(jù)結(jié)構(gòu)實現(xiàn)
系統(tǒng)命令:調(diào)用grep
Into/From 及其在 String 和 &str 互轉(zhuǎn)上的應用
共享內(nèi)存
Sublime
網(wǎng)絡模塊:W貓的回音
函數(shù)返回值
包和模塊
高階函數(shù)
函數(shù)與方法
match關(guān)鍵字
隊列
目錄操作:簡單grep
語句和表達式
并發(fā)編程
閉包
測試
閉包的語法
同步
迭代器
String
Send 和 Sync
Rc 和 Arc
屬性
Emacs
優(yōu)先隊列
Prelude
cargo簡介
控制流(control flow)
數(shù)組、動態(tài)數(shù)組和字符串
FFI
模塊和包系統(tǒng)、Prelude
實戰(zhàn)篇
Rust 是一門系統(tǒng)級編程語言,被設(shè)計為保證內(nèi)存和線程安全,并防止段錯誤。作為系統(tǒng)級編程語言,它的基本理念是 “零開銷抽象”。理
運算符重載
Any和反射
rust數(shù)據(jù)庫操作
輸入輸出流
復合類型
性能測試

特性

特性與接口

為了描述類型可以實現(xiàn)的抽象接口 (abstract interface), Rust引入了特性 (trait) 來定義函數(shù)類型簽名 (function type signature):

trait HasArea {
    fn area(&self) -> f64;
}

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

impl HasArea for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

struct Square {
    x: f64,
    y: f64,
    side: f64,
}

impl HasArea for Square {
    fn area(&self) -> f64 {
        self.side * self.side
    }
}

fn print_area<T: HasArea>(shape: T) {
    println!("This shape has an area of {}", shape.area());
}

其中函數(shù)print_area()中的泛型參數(shù)T被添加了一個名為HasArea的特性約束 (trait constraint), 用以確保任何實現(xiàn)了HasArea的類型將擁有一個.area()方法。 如果需要多個特性限定 (multiple trait bounds),可以使用+

use std::fmt::Debug;

fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
    x.clone();
    y.clone();
    println!("{:?}", y);
}

fn bar<T, K>(x: T, y: K)
    where T: Clone,
          K: Clone + Debug
{
    x.clone();
    y.clone();
    println!("{:?}", y);
}

其中第二個例子使用了更靈活的where從句,它還允許限定的左側(cè)可以是任意類型, 而不僅僅是類型參數(shù)。

定義在特性中的方法稱為默認方法 (default method),可以被該特性的實現(xiàn)覆蓋。 此外,特性之間也可以存在繼承 (inheritance):

trait Foo {
    fn foo(&self);

    // default method
    fn bar(&self) { println!("We called bar."); }
}

// inheritance
trait FooBar : Foo {
    fn foobar(&self);
}

struct Baz;

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

impl FooBar for Baz {
    fn foobar(&self) { println!("foobar"); }
}

如果兩個不同特性的方法具有相同的名稱,可以使用通用函數(shù)調(diào)用語法 (universal function call syntax):

// short-hand form
Trait::method(args);

// expanded form
<Type as Trait>::method(args);

關(guān)于實現(xiàn)特性的幾條限制:

  • 如果一個特性不在當前作用域內(nèi),它就不能被實現(xiàn)。
  • 不管是特性還是impl,都只能在當前的包裝箱內(nèi)起作用。
  • 帶有特性約束的泛型函數(shù)使用單態(tài)化實現(xiàn) (monomorphization), 所以它是靜態(tài)派分的 (statically dispatched)。

下面列舉幾個非常有用的標準庫特性:

  • Drop提供了當一個值退出作用域后執(zhí)行代碼的功能,它只有一個drop(&mut self)方法。
  • Borrow用于創(chuàng)建一個數(shù)據(jù)結(jié)構(gòu)時把擁有和借用的值看作等同。
  • AsRef用于在泛型中把一個值轉(zhuǎn)換為引用。
  • Deref<Target=T>用于把&U類型的值自動轉(zhuǎn)換為&T類型。
  • Iterator用于在集合 (collection) 和惰性值生成器 (lazy value generator) 上實現(xiàn)迭代器。
  • Sized用于標記運行時長度固定的類型,而不定長的切片和特性必須放在指針后面使其運行時長度已知, 比如&[T]Box<Trait>。

泛型和多態(tài)

泛型 (generics) 在類型理論中稱作參數(shù)多態(tài) (parametric polymorphism), 意為對于給定參數(shù)可以有多種形式的函數(shù)或類型。先看Rust中的一個泛型例子:

Option在rust標準庫中的定義:

enum Option<T> {
    Some(T),
    None,
}

Option的典型用法:

let x: Option<i32> = Some(5);
let y: Option<f64> = Some(5.0f64);

其中<T>部分表明它是一個泛型數(shù)據(jù)類型。當然,泛型參數(shù)也可以用于函數(shù)參數(shù)和結(jié)構(gòu)體域:

// generic functions
fn make_pair<T, U>(a: T, b: U) -> (T, U) {
    (a, b)
}
let couple = make_pair("man", "female");

// generic structs
struct Point<T> {
    x: T,
    y: T,
}
let int_origin = Point { x: 0, y: 0 };
let float_origin = Point { x: 0.0, y: 0.0 };

對于多態(tài)函數(shù),存在兩種派分 (dispatch) 機制:靜態(tài)派分和動態(tài)派分。 前者類似于C++的模板,Rust會生成適用于指定類型的特殊函數(shù),然后在被調(diào)用的位置進行替換, 好處是允許函數(shù)被內(nèi)聯(lián)調(diào)用,運行比較快,但是會導致代碼膨脹 (code bloat); 后者類似于Java或Go的interface,Rust通過引入特性對象 (trait object) 來實現(xiàn), 在運行期查找虛表 (vtable) 來選擇執(zhí)行的方法。特性對象&Foo具有和特性Foo相同的名稱, 通過轉(zhuǎn)換 (casting) 或者強制多態(tài)化 (coercing) 一個指向具體類型的指針來創(chuàng)建。

當然,特性也可以接受泛型參數(shù)。但是,往往更好的處理方式是使用關(guān)聯(lián)類型 (associated type):

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

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

}

// use associated types
trait Graph {
    type N;
    type E;

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

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

}

struct Node;

struct Edge;

struct SimpleGraph;

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

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

    }

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

    }
}

let graph = SimpleGraph;
let object = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
上一篇:復合類型下一篇:Rust旅程