Rust 中的Trait和泛型
Trait
trai
类似于其它语言中的“接口”或“抽象函数”,它可以为多个不同的类型
定义一个共有的抽象方法,也可以用来实现泛型约束
trait 中的方法也可以定义默认实现,默认实现的方法可以调用trait中的其它方法,即使这些方法没有默认实现
使用trait的类型也可以重载trait中已经有默认实现的方法;但是无法从方法的重写实现中调用该方法的默认实现
定义一个trait
定义一个trait,这个trait里有两个方法info()
和say_hello()
,其中say_hello()
具有默认实现
// 定义一个 trait, 其中有一个 info 函数来表示输出类型的基本信息
trait Info {
fn info(&self) {}
fn say_hello(&self) {
println!("Hello!");
}
}
定义使用这个trait的类型
定义两个结构体
struct People {
name: String,
age: u8,
}
struct Book {
name: String,
author: String,
price: f32,
}
// 为 People 定义 trait 的实现
impl Info for People {
fn info(&self) {
println!("姓名:{}, 年龄:{}", self.name, self.age);
}
// 重载 trait 中 say_hello 的默认实现
fn say_hello(&self) {
println!("Hello, {}", self.name);
}
}
// 为 Book 绑定 trait 实现
impl Info for Book {
fn info(&self) {
println!("书名:{}, 作者:{}, 单价:{}", self.name, self.author, self.price);
}
}
简单使用
fn main() {
let a = People{
name: String::from("Zhangsan"),
age: 18,
};
let b = Book{
name: String::from("Rust"),
author: String::from("unKnown"),
price: 34.56,
};
a.info();
b.info();
a.say_hello(); // a 定义了自己的 say_hello 方法实现, 因此将覆盖掉 trait 的默认实现而使用自己定义的实现
b.say_hello(); // b 没有定义自己的 say_hello 方法实现, 因此使用 trait 默认的实现
}
/* 输出:
姓名:Zhangsan, 年龄:18
书名:Rust, 作者:unKnown, 单价:34.56
Hello, Zhangsan
Hello!
*/
将 trait 作为函数参数的类型使用
定义两个函数,它们的参数类型为实现了 trait 的类型,有如下两种方式为函数的参数指定为 trait 类型,通常在只有一个 trait 的时候更推荐方式二,而在有多个参数每个参数需要实现多个 trait 时更推荐方式三;其实方式一就是方式二的一个语法糖
// 方式一
fn test_fn(a: &impl Info) {
a.info();
a.say_hello();
}
// 方式二,如果该参数需要使用多个 trait 则使用 '+' 号进行连接, 如 T: Info + Display
fn test_fn_02<T: Info>(a: &T) {
a.info();
a.say_hello();
}
// 方式三, 同样的,如果参数需要满足多个 trait 则使用 '+' 号进行连接
fn test_fn_03<T>(a: &T)
where T: Info
{
a.info();
a.say_hello();
}
使用这个函数:
fn main() {
let a = People{
name: String::from("Zhangsan"),
age: 18,
};
let b = Book{
name: String::from("Rust"),
author: String::from("unKnown"),
price: 34.56,
};
test_fn_01(&a);
test_fn_02(&b);
test_fn_03(&a);
}
/* 输出:
姓名:Zhangsan, 年龄:18
Hello, Zhangsan
书名:Rust, 作者:unKnown, 单价:34.56
Hello!
姓名:Zhangsan, 年龄:18
Hello, Zhangsan
*/
泛型
如下,定义一个求和函数,使其既能满足使用整型作为参数,也能满足使用浮点型作为参数
use std::ops::Add;
fn main() {
let a = 123;
let b = 456;
let m = 123.456;
let n = 456.789;
let x = my_sum(a, b);
let y = my_sum(m, n);
println!("x = {}, y = {}", x, y);
}
fn my_sum<T: Add<Output = T>>(a: T, b: T) -> T {
a + b
}
/* 输出:
x = 579, y = 580.245
*/
评论区