也就是 Trait 和 Generics。
Rust 没有的 Class 和继承功能由 Struct 和 Trait 来实现了(个人理解)。
泛型 | Generics
泛型:不特定某种类型。在需要抽象、重复使用的地方经常用到。不关心具体的类型,只关心类型的实现。在 Rust 中,泛型不光指泛型参数,也指接受泛型参数的泛型函数。
定义一个接受泛型参数的函数:
// 使用到的泛型要在前面用<>提出。
// T 按常理推断为泛型,即使在之前被定义为结构体。
fn function<T>(a:T){
//...
}
特性 | Trait
特性:定义可共享的行为。拥有某种特性即需要实现某种方法。比如常见的std::fmt::Display
,实现它才能在println!
或format
里直接转换字符串。
//定义一个特性
pub trait Identification {
fn get_code(&self) -> String;
}
//在类型上实现特性:
pub struct User {
pub name: String,
pub id: String,
}
impl Identification for User {
fn get_code(&self) -> String {
format!("{}-{}", self.name, self.id)
}
}
//然后就可以使用了:
fn main() {
let user = User {
name: "username".to_string(),
id: "123456789".to_string(),
};
println!("{}", user.get_code());
}
// 输出:username-123456789
默认操作
如果需要对特性进行默认的基础操作实现,则:
pub trait Identification {
fn get_code(&self) -> String{
"默认代码……".to_string()
}
}
// 中略
//只定义实现特性,不定义内容
impl Identification for User {}
//再运行,则输出为:
//默认代码……
参数约束
特性更多是一种约束,约定操作对象需要实现的方法。在函数的参数中使用特性约束:
pub fn show_identity(user: &impl Identification) {
println!("识别码:{}", user.get_code());
}
则只有实现了该特性的参数能通过检测。例:
pub trait Identification {
fn get_code(&self) -> String;
}
pub struct User {
pub name: String,
pub id: String,
}
impl Identification for User {
fn get_code(&self) -> String {
format!("{}-{}", self.name, self.id)
}
}
//不实现特性
pub struct Member {
pub name: String,
pub id: String,
}
pub fn show_identity(user: &impl Identification) {
println!("识别码:{}", user.get_code());
}
fn main() {
let user = User {
name: "username".to_string(),
id: "123456789".to_string(),
};
let mem = Member {
name: "membername".to_string(),
id: "123456789".to_string(),
};
show_identity(&user);
show_identity(&mem);
}
运行报错:
error[E0277]: the trait bound `Member: Identification` is not satisfied
--> trait.rs:37:19
|
21 | pub fn show_identity(user: &impl Identification) {
| -------------- required by this bound in `show_identity`
...
37 | show_identity(&mem);
| ^^^^ the trait `Identification` is not implemented for `Member`
🍭 还有语法糖简写版,当多个参数需要符合同一特性时,将其定义为泛型:
pub fn show_identity(user: &impl Identification, user2:&impl Identification)
//可以写成
pub fn show_identity<T:Identification>(user: &T, user2:&T)
要求多个特性的情况:
pub fn show_identity(user:&(impl Identification + std::fmt::Display))
//可以写成
pub fn show_identity<T:Identification + std::fmt::Display>(user:&T)
再加多一点糖,使用where
,接近我在 docs.rs 里看不懂的样子了:
pub fn show_identity(user:&(impl Identification + std::fmt::Display))
//可以写成
pub fn show_identity<T>(user: &T)
where
T: Identification + std::fmt::Display,
参考资料
- Traits: Defining Shared Behavior
- Generics - Rust By Example
- 封面图片:Photo by Hannah Morgan on Unsplash