Rust 入门 Trait
Trait
- Trait 翻译为 特性 特点
- Trait 是抽象的定义共享行为
- 与其他语言中的接口类似, 但是有些区别
定义
- 把方法签名放在一起, 用于定义实现某种目的所必须的一组行为
- Trait 中只有方法的签名, 没有方法的实现(在没有默认实现的情况下)
- Trait 中可以有多个方法, 无需实现方法体
- 实现该 Trait 的方法必须提供具体的方法实现
pub trait Summary {
fn summarize(&self) -> String;
}
实现
- 实现 Trait 时使用
impl Xx for Xxx{}
- 在
impl
块中需要对 Trait 中定义的方法进行具体的实现(在没有默认实现的情况下)
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
impl Summary for NewsArticle {
fn summarize(&self) -> String {
format!("{}, by {} ({})", self.headline, self.author, self.location)
}
}
impl Summary for Tweet {
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
约束
- 可以再某个类型上实现某个 trait 的前提条件:
- 这个类型或者这个 trait 是在本地代码中定义的
- 无法为外部的类型实现外部的 trait:
- 这个限制是程序属性的一部分(一致性)
- 根据体的说就是孤儿原则
- 此规则确保其他人的代码不能被您破坏, 反之亦然
- 如果没有此规则, 两个 crate 可以为同一类型实现相同的 trait, Rust 编译器就不知道应该使用哪个 crate 中的实现了
默认实现
- 有时为 trait 中的某些或全部方法提供默认的行为
- 而不是在每个类型的每个实现中都定义自己的行为是很有用的
- 这样当为某个特定类型实现 trait 时
- 可以选择保留或重载每个方法的默认行为
pub trait Summary {
fn summarize(&self) -> String{
String::from("默认实现")
}
}
pub struct NewsArticle {
pub headline: String,
pub location: String,
pub author: String,
pub content: String,
}
pub struct Tweet {
pub username: String,
pub content: String,
pub reply: bool,
pub retweet: bool,
}
impl Summary for NewsArticle {
// 使用默认实现
}
impl Summary for Tweet {
// 重写默认实现
fn summarize(&self) -> String {
format!("{}: {}", self.username, self.content)
}
}
- 默认实现的方法可以调用 trait 中的其他方法
pub trait Summary {
fn summarize(&self) -> String;
fn author(&self) -> String {
format!("默认实现: {}", self.summarize())
}
}
注: 无法从重写的方法内调用默认方法
Trait bounds
- impl Trait语法
- 此方法只能用于一些简单的情况下
pub trait Summary {
fn summarize(&self) -> String;
}
// item 的类型为: 实现了Summary的任意类型
fn notify(item: impl Summary) {
}
- 如何使用多个 Trait 约束?
- 可以使用
+
指定多个 Trait
- 可以使用
use std::fmt::Display;
fn notify(item: impl Summary + Display) {
}
- Trait bounds语法
- 此方法用于一些复杂的情况
- 实际上 impl Trait 语法是此方法的一种简写
use std::fmt::Display;
fn notify<T: Summary>(item: T, old: T) {
}
// 指定多个 Trait
fn send<T: Summary + Display>(item: T) {
}
- where 字句
- 使用过多的 Trait bounds 也有缺点
每个泛型有其自己的 Trait bounds
所以有多个泛型参数的函数在名称和参数列表之间会有很长的 trait bound 信息
这使得函数签名难以阅读 - where 字句 编写在 方法签名后面, 用来约束泛型
- 使用过多的 Trait bounds 也有缺点
// Trait bounds 语法
fn notify<T: Summary + Display, E: Clone + Debug>(a: T, b: E) {
}
// where 字句
fn notify2<T, E>(a: T, b: E)
where
T: Summary + Display,
E: Clone + Debug,
{
}
使用 Trait bounds 的例子
// 此方法用于获取切片中的最大值
fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut result = &list[0];
for item in list.iter() {
if item > result {
result = item;
}
}
result
}
fn main() {
let arr = [1, 3, 5, 7, 9, 5, 6, 11, 10, 5, 6];
let value = largest(&arr);
println!("最大值为: {}", value);
let arr = ['a', 'q', 'f', 'c', 'p', '[', 'x'];
let value = largest(&arr);
println!("最大值为: {}", value);
let arr = ["关注", "收藏", "推荐"];
let value = largest(&arr);
println!("最大值为: {}", value);
}
如果对我分享的内容感兴趣的话 记得关注我得动态
求推荐 求收藏 求转发 求关注
求推荐 求收藏 求转发 求关注