- 第1章:基础
Rust 泛型与特性
C++ 语言中用"模板"来实现泛型,而 C 语言中没有泛型的机制,这也导致 C 语言难以构建类型复杂的工程。
泛型机制是编程语言用于表达类型抽象的机制,一般用于功能确定、数据类型待定的类,如链表、映射表等。
fn max(array: &[i32]) -> i32 {
let mut max_index = 0; let mut i = 1; while i < array.len() {
if array[i] > array[max_index] {
max_index = i;
} i += 1;
} array[max_index]}
fn main() {
let a = [2,
4,
6,
3,
1]; println!("max = {}", max(&a));
}
fn max < T > (array: &[T]) -> T { let mut max_index = 0; let mut i = 1; while i < array.len() { if array[i] > array[max_index] { max_index = i; } i += 1; } array[max_index] }
Rust 中的结构体和枚举类都可以实现泛型机制。
struct Point<T> {
x: T,
y: T
}
let p1 = Point {x: 1, y: 2};
let p2 = Point {x: 1.0, y: 2.0};
let p = Point {x: 1, y: 2.0};
struct Point<T1, T2> {
x: T1,
y: T2
}
enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
struct Point < T > {
x: T,
y: T,
} impl < T > Point < T > {
fn x(&self) -> &T {
&self.x
}}fn main() {
let p = Point {
x: 1,
y: 2
};
println!("p.x = {}", p.x());
}
运行结果:impl Point<f64> {
fn x(&self) -> f64 {
self.x
}
}
impl<T, U> Point<T, U> {
fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
Point {
x: self.x,
y: other.y,
}
}
}
特性在 Rust 中用 trait 表示:
trait Descriptive {
fn describe(&self) -> String;
}
Descriptive 规定了实现者必需有 describe(&self) -> String 方法。
我们用它实现一个结构体:
trait Descriptive {
fn describe(&self) -> String;
}
fn main() {
struct Person {
name: String,
age: u8
}
impl Descriptive for Person {
fn describe(&self) -> String {
format!("{} {}", self.name, self.age)
}
}
}
格式是:
trait Descriptive {
fn describe(&self) -> String {
String::from("[Object]")
}}struct Person {
name: String,
age: u8
}impl Descriptive for Person {
fn describe(&self) -> String {
format!("{} {}", self.name, self.age)
}}
fn main() {
let cali = Person {
name: String::from("Cali"),
age: 24
};
println!("{}", cali.describe());
}
fn output(object: impl Descriptive) {
println!("{}", object.describe());
}
特性参数还可以用这种等效语法实现:
fn output<T: Descriptive>(object: T) {
println!("{}", object.describe());
}
fn output_two<T: Descriptive>(arg1: T, arg2: T) {
println!("{}", arg1.describe());
println!("{}", arg2.describe());
}
fn notify(item: impl Summary + Display)
fn notify<T: Summary + Display>(item: T)
复杂的实现关系可以使用 where 关键字简化,例如:
fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U)
fn some_function<T, U>(t: T, u: U) -> i32
where T: Display + Clone,
U: Clone + Debug
trait Comparable {
fn compare(&self, object: &Self) -> i8;
}
fn max < T: Comparable > (array: &[T]) -> &T {
let mut max_index = 0; let mut i = 1; while i < array.len() {
if array[i].compare(&array[max_index]) > 0 {
max_index = i;
} i += 1;
} &array[max_index]}impl Comparable for f64 {
fn compare(&self, object: &f64) -> i8 {
if &self > &object {
1
} else if &self == &object {
0
} else {
-1
}
}
}
fn main() {
let arr = [1.0,
3.0,
5.0,
4.0,
2.0]; println!("maximum of arr is {}", max(&arr));
}
fn person() -> impl Descriptive {
Person {
name: String::from("Cali"),
age: 24
}
}
但是有一点,特性做返回值只接受实现了该特性的对象做返回值且在同一个函数中所有可能的返回值类型必须完全一样。比如结构体 A 与结构体 B 都实现了特性 Trait,下面这个函数就是错误的:
fn some_function(bool bl) -> impl Descriptive {
if bl {
return A {};
} else {
return B {};
}
}
有条件实现方法
impl 功能十分强大,我们可以用它实现类的方法。但对于泛型类来说,有时我们需要区分一下它所属的泛型已经实现的方法来决定它接下来该实现的方法:
struct A<T> {}
impl<T: B + C> A<T> {
fn d(&self) {}
}
网友评论0