====== 泛型与 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'' 子句简化复杂约束