PDF版 ePub版

# 特征

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

impl Circle {
fn area(&self) -> f64 {
}
}

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

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

impl HasArea for Circle {
fn area(&self) -> f64 {
}
}

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

Rust 可能会抱怨道：

error: type T does not implement any method in scope named area

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

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

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

impl HasArea for Circle {
fn area(&self) -> f64 {
}
}

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());
}

fn main() {
let c = Circle {
x: 0.0f64,
y: 0.0f64,
};

let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 1.0f64,
};

print_area(c);
print_area(s);
}

This shape has an area of 3.141593
This shape has an area of 1

print_area(5);

error: failed to find an implementation of trait main::HasArea for int

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

impl HasArea for i32 {
fn area(&self) -> f64 {
println!("this is silly");

*self as f64
}
}

5.area();

let mut f = std::fs::File::open("foo.txt").ok().expect("Couldn’t open foo.txt");
let result = f.write("whatever".as_bytes());

error: type std::fs::File does not implement any method in scope named write

let result = f.write(b"whatever");

use std::io::Write;

let mut f = std::fs::File::open("foo.txt").ok().expect("Couldn’t open foo.txt");
let result = f.write("whatever".as_bytes());

## 多个特征边界

fn foo<T: Clone>(x: T) {
x.clone();
}

use std::fmt::Debug;

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

T 现在需要复制以及调试。

## Where 子句

use std::fmt::Debug;

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

Rust 已经有了解决方法，这就是所谓的“where 子句”：

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);
}

fn main() {
foo("Hello", "world");
bar("Hello", "workd");
}

foo()使用我们之前讲解的语法，bar()使用一个 where 子句。所有你需要做的就是定义类型参数时不要定义边界，然后在参数列表之后添加 where 语句。对于更长的列表，可以添加空格：

use std::fmt::Debug;

fn bar<T, K>(x: T, y: K)
where T: Clone,
K: Clone + Debug {

x.clone();
y.clone();
println!("{:?}", y);
}

Where 语句也比简单的语法更加强大。例如：

trait ConvertTo<Output> {
fn convert(&self) -> Output;
}

impl ConvertTo<i64> for i32 {
fn convert(&self) -> i64 { *self as i64 }
}

// can be called with T == i32
fn normal<T: ConvertTo<i64>>(x: &T) -> i64 {
x.convert()
}

// can be called with T == i64
fn inverse<T>() -> T
// this is using ConvertTo as if it were "ConvertFrom<i32>"
where i32: ConvertTo<T> {
1i32.convert()
}

## 默认的方法

trait Foo {
fn bar(&self);

fn baz(&self) { println!("We called baz."); }
}

Foo 特征的实现者需要实现 bar()方法，但是他们不需要实现 baz()。他们会得到这种默认行为。如果他们这么选择的话就可以覆盖默认的情形：

struct UseDefault;

impl Foo for UseDefault {
fn bar(&self) { println!("We called bar."); }
}

struct OverrideDefault;

impl Foo for OverrideDefault {
fn bar(&self) { println!("We called bar."); }

fn baz(&self) { println!("Override baz!"); }
}

let default = UseDefault;
default.baz(); // prints "We called baz."

let over = OverrideDefault;
over.baz(); // prints "Override baz!"
⇱

## 继承

trait Foo {
fn foo(&self);
}

trait FooBar : Foo {
fn foobar(&self);
}
FooBar的实现者也要实现Foo,像这样:
struct Baz;

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

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

error: the trait main::Foo is not implemented for the type main::Baz [E027]