====== 泛型与 Trait ======
===== 泛型(Generics) =====
泛型允许编写适用于多种类型的代码,避免重复。
==== 泛型函数 ====
fn largest(list: &[T]) -> &T {
let mut largest = &list[0];
for item in list {
if item > largest { // 这里需要 PartialOrd 约束
largest = item;
}
}
largest
}
fn main() {
let numbers = vec![34, 50, 25, 100, 65];
println!("最大: {}", largest(&numbers));
let chars = vec!['y', 'm', 'a', 'q'];
println!("最大: {}", largest(&chars));
}
注意:以上代码需要加 ''PartialOrd'' 约束才能编译,我们稍后介绍。
==== 泛型结构体 ====
struct Point {
x: T,
y: T,
}
fn main() {
let integer = Point { x: 5, y: 10 }; // Point
let float = Point { x: 1.0, y: 4.0 }; // Point
}
==== 泛型结构体多个类型参数 ====
struct Point {
x: T,
y: U,
}
fn main() {
let both = Point { x: 5, y: 4.0 }; // Point
}
==== 泛型枚举 ====
enum Option {
Some(T),
None,
}
enum Result {
Ok(T),
Err(E),
}
==== 泛型方法 ====
struct Point {
x: T,
y: T,
}
impl Point {
fn x(&self) -> &T {
&self.x
}
}
// 专门为 f64 类型实现的方法
impl Point {
fn distance_from_origin(&self) -> f64 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
fn main() {
let p = Point { x: 5, y: 10 };
println!("p.x = {}", p.x());
let f = Point { x: 3.0, y: 4.0 };
println!("距离原点: {}", f.distance_from_origin());
}
===== Trait =====
Trait 定义共享行为,类似于其他语言的接口(interface)。
==== 定义和实现 Trait ====
trait Summary {
fn summarize(&self) -> String;
}
struct Article {
title: String,
author: String,
content: String,
}
impl Summary for Article {
fn summarize(&self) -> String {
format!("《{}》- {}", self.title, self.author)
}
}
struct Tweet {
username: String,
content: String,
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("@{}: {}", self.username, self.content)
}
}
fn main() {
let article = Article {
title: String::from("Rust 入门"),
author: String::from("小明"),
content: String::from("内容..."),
};
println!("{}", article.summarize());
let tweet = Tweet {
username: String::from("rust_fan"),
content: String::from("学习 Rust 中!"),
};
println!("{}", tweet.summarize());
}
==== 默认实现 ====
Trait 可以提供默认方法实现:
trait Summary {
fn summarize(&self) -> String {
String::from("(阅读更多...)")
}
}
impl Summary for Article {} // 使用默认实现
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("@{}: {}", self.username, self.content)
}
}
==== Trait 作为参数 ====
// 方式一:impl Trait 语法
fn notify(item: impl Summary) {
println!("通知: {}", item.summarize());
}
// 方式二:Trait Bound 语法
fn notify(item: T) {
println!("通知: {}", item.summarize());
}
// 多个参数
fn notify2(item1: impl Summary, item2: impl Summary) {}
fn notify2(item1: T, item2: T) {}
==== 多重约束 ====
use std::fmt::Display;
// 同时要求 impl Summary + Display
fn notify(item: impl Summary + Display) {}
// 或使用 where 子句
fn some(t: T, u: U)
where
T: Display + Clone,
U: Clone + Summary,
{}
==== 返回 Trait ====
fn returns_summarizable() -> impl Summary {
Article {
title: String::from("Rust 泛型和 Trait"),
author: String::from("老师"),
content: String::from("内容..."),
}
}
===== 常用标准库 Trait =====
^ Trait ^ 用途 ^
| ''Clone'' | 提供 ''clone()'' 方法进行深拷贝 |
| ''Copy'' | 标记类型使用按位复制(栈上类型) |
| ''Debug'' | 提供 ''{:?}'' 格式化 |
| ''Display'' | 提供 ''{}'' 格式化 |
| ''PartialEq'' | 提供 ''=='', ''!='' 比较 |
| ''PartialOrd'' | 提供 ''<'', ''>'', ''<='', ''>='' 比较 |
| ''Hash'' | 提供哈希计算 |
| ''Iterator'' | 实现迭代器 |
===== 本章实践 =====
use std::fmt::Display;
trait Greet {
fn greet(&self) -> String;
}
struct Person {
name: String,
age: u8,
}
impl Greet for Person {
fn greet(&self) -> String {
format!("你好,我叫{},今年{}岁", self.name, self.age)
}
}
fn print_greet(item: impl Greet + Display) {
println!("{}", item.greet());
}
fn main() {
let p = Person {
name: "小明".into(),
age: 25,
};
print_greet(p);
}
===== 本章小结 =====
* 泛型允许编写类型无关的代码
* ''impl'' 为泛型类型实现方法
* Trait 定义共享行为,类似接口
* ''impl Trait'' 和 ''T: Trait'' 两种约束写法
* ''where'' 子句简化复杂约束