泛型(generics)
// 泛型枚举(generic enums)
enum Option<T> {
Some(T),
None,
}
let x: Option<i32> = Some(5);
let y: Option<f64> = Some(5.0f64);
enum Result<T, E> {
Ok(T),
Err(E),
}
// 泛型函数(generic functions)
fn takes_anything<T>(x: T) {
// do something with x
}
fn takes_two_of_the_same_things<T>(x: T, y: T) {
// ...
}
fn takes_two_things<T, U>(x: T, y: U) {
// ...
}
// 泛型结构体(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 };
impl<T> Point<T> {
fn swap(&mut self) {
std::mem::swap(&mut self.x, &mut self.y);
}
}
特质(traits)
- 特质大致相当于Java和C#中的接口。
- 特质内通常只包含方法的签名,实现某个特质需要实现特质内的所有方法。
- 特质内的方法可以有缺省实现。缺省方法(default methods)中的实现可以被覆盖(overridden)。
- 一个特质可以继承另一个特质。
- 使用deriving特性可以自动实现某些特质。
// 特质
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)
}
}
// 为其他类型实现特质
trait HasArea {
fn area(&self) -> f64;
}
impl HasArea for i32 {
fn area(&self) -> f64 {
println!("this is silly");
*self as f64
}
}
5.area();
// 特质的缺省方法
trait Foo {
fn is_valid(&self) -> bool;
fn is_invalid(&self) -> bool { !self.is_valid() }
}
struct UseDefault;
impl Foo for UseDefault {
fn is_valid(&self) -> bool {
println!("Called UseDefault.is_valid.");
true
}
}
struct OverrideDefault;
impl Foo for OverrideDefault {
fn is_valid(&self) -> bool {
println!("Called OverrideDefault.is_valid.");
true
}
fn is_invalid(&self) -> bool {
println!("Called OverrideDefault.is_invalid!");
true // overrides the expected value of is_invalid()
}
}
let default = UseDefault;
assert!(!default.is_invalid()); // prints "Called UseDefault.is_valid."
let over = OverrideDefault;
assert!(over.is_invalid()); // prints "Called OverrideDefault.is_invalid!"
// 特质的继承(inheritance)
trait Foo {
fn foo(&self);
}
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"); }
}
// deriving
#[derive(Debug)]
struct Foo;
fn main() {
println!("{:?}", Foo);
}
特质边界(trait bounds)与特质对象(trait objects)
- 特质可以被用于泛型约束以实现静多态(static dispatch)。用于泛型约束的特质被称作泛型的特质边界。
- 特质可以被用作类型以实现动多态(dynamic dispatch)。特质类型的引用被称作特质对象。
- 一个泛型类型可以指定多个特质边界,复杂情况下还可以使用where子句。
// 特质的应用
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_static<T: HasArea>(shape: &T) {
println!("This shape has an area of {}", shape.area());
}
// 特质对象,动多态
fn print_area_dynamic(shape: &HasArea) {
println!("This shape has an area of {}", shape.area());
}
fn main() {
let c = Circle {
x: 0.0f64,
y: 0.0f64,
radius: 1.0f64,
};
let s = Square {
x: 0.0f64,
y: 0.0f64,
side: 1.0f64,
};
print_area_static(&c); // This shape has an area of 3.141592653589793
print_area_static(&s); // This shape has an area of 1
print_area_dynamic(&c); // This shape has an area of 3.141592653589793
print_area_dynamic(&s); // This shape has an area of 1
}
// 泛型结构体的特质边界
struct Rectangle<T> {
x: T,
y: T,
width: T,
height: T,
}
impl<T: PartialEq> Rectangle<T> {
fn is_square(&self) -> bool {
self.width == self.height
}
}
fn main() {
let mut r = Rectangle {
x: 0,
y: 0,
width: 47,
height: 47,
};
assert!(r.is_square());
r.height = 42;
assert!(!r.is_square());
}
// 多重特质边界
fn foo<T: Clone>(x: T) {
x.clone();
}
use std::fmt::Debug;
fn foo<T: Clone + Debug>(x: T) {
x.clone();
println!("{:?}", x);
}
// 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", "world");
}
Drop特质
// 实现Drop特质
struct Firework {
strength: i32,
}
impl Drop for Firework {
fn drop(&mut self) {
println!("BOOM times {}!!!", self.strength);
}
}
fn main() {
let firecracker = Firework { strength: 1 };
let tnt = Firework { strength: 100 };
}
// BOOM times 100!!!
// BOOM times 1!!!
通用函数调用语法(universal function call syntax)
// 通用函数调用语法
trait Foo {
fn foo() -> i32;
}
struct Bar;
impl Bar {
fn foo() -> i32 {
20
}
}
impl Foo for Bar {
fn foo() -> i32 {
10
}
}
fn main() {
assert_eq!(10, <Bar as Foo>::foo());
assert_eq!(20, Bar::foo());
}