Rust中Trait
用来定义某种类型具有哪些并且可以与其他类型共享的功(或行为)
介绍
Trait
本意为特点,与其他语言的 接口(interface)
相似,但也有不同。
Trait bounds(约束)
:泛型类型参数指定为实现了特定行为的类型。
定义 Trait
Trait 是把方法签名放在一起,来定义实现某种目的所必需的一组行为。Trait 特征如下:
- 使用 trait 关键字定义
- 只有方法签名,没有具体实现,多个方法以
;
结尾 - 实现 trait 必需提供具体的方法实现
pub trait Trait名称 {
fn 方法名1(&self) -> 返回值1;
fn 方法名2(参数...) -> 返回值2;
...
}
实现 Trait
impl Trait名称 for 结构体名称.. {
fn 方法名1(&self) -> 返回值1 {
...
}
fn 方法名2(参数...) -> 返回值2 {
...
}
...
}
说明:
- Trait 的方法需要在
impl
代码块里对方法签名进行实现
pub trait Summary {
fn summary(&self) -> String;
}
pub struct BlogPost {
pub title: String,
pub author: String,
pub content: String,
}
impl Summary for BlogPost {
fn summary(&self) -> String {
format!("{} by {}", self.title, self.author)
}
}
fn main() {
let p = BlogPost {
title: String::from("some title"),
author: String::from("xiexianbin"),
content: String::from("abcd23"),
};
println!("{}", p.summary())
}
实现 trait 的约束:
- 某类型实现 trait 的前提条件:该类型或该 trait 是在本地 crate 里定义的
- 无法为外部类型来实现外部的 trait,如无法在标准库外为某个类型实现
Display
trait - Trait 可以加默认实现,该实现可以重写,若需要采用默认实现,
impl
块中不需要添加具体实现- 默认实现可以调用 trait 中其他的方法,即使该方法没有默认实现也可以
- 无法在重写实现中调用默认实现,即不支持其他语言的
supper.方法()
调用
pub trait Summary {
fn summary(&self) -> String {
format!("some thing...")
}
}
pub struct BlogPost {
pub title: String,
pub author: String,
pub content: String,
}
impl Summary for BlogPost {
}
fn main() {
let p = BlogPost {
title: String::from("some title"),
author: String::from("xiexianbin"),
content: String::from("abcd23"),
};
println!("{}", p.summary())
}
Trait 作为参数
实现方式:
- 使用
impl Trait名称
作为参数:简单情况 - 使用
trait bound
语法:复杂情况impl trait
语法是 trait bound
的语法糖
- 使用
+
指定多个 trait bound
,如:pub fn summary3(i: impl Summary + Display) {}
pub fn summary4<T: Summary + Display>(i: T) {}
trait bound
使用 where 子句,解决上面展示复杂问题
use std::fmt::{Display, Debug};
pub trait Summary {
fn summary(&self) -> String;
}
pub struct BlogPost {
pub title: String,
pub author: String,
pub content: String,
}
impl Summary for BlogPost {
fn summary(&self) -> String {
format!("{} by {}", self.title, self.author)
}
}
// 简单写法
//pub fn summary1(i: &impl Summary) {
pub fn summary1(i: impl Summary) {
println!("{}", i.summary())
}
// trait bound 语法
//pub fn summary2<T: Summary>(i: &T) {
pub fn summary2<T: Summary>(i: T) {
println!("{}", i.summary())
}
// 实现多个 trait
pub fn summary3(i: impl Summary + Display) {
println!("{}", i.summary())
}
pub fn summary4<T: Summary + Display>(i: T) {
println!("{}", i.summary())
}
// where 子句,类似于 c# 的写法
pub fn summary5<T, U>(x: T, y: U) -> String
where
T: Summary + Display,
U: Debug,
{
format!("{}", x.summary())
}
fn main() {
let p = BlogPost {
title: String::from("some title"),
author: String::from("xiexianbin"),
content: String::from("abcd23"),
};
// summary1(p);
summary2(p);
}
Trait 作为返回类型
impl Trait
语法impl Trait
只能返回确定的同一种类型,返回多种类型会报错
pub trait Summary {
fn summary(&self) -> String;
}
pub struct BlogPost {
pub title: String,
pub author: String,
pub content: String,
}
impl Summary for BlogPost {
fn summary(&self) -> String {
format!("{} by {}", self.title, self.author)
}
}
// 只能返回特定类型
pub fn new_blog_post(title: String, author: String, content: String) -> impl Summary {
BlogPost {
title,
author,
content,
}
}
fn main() {
let p = new_blog_post(
String::from("some title"),
String::from("xiexianbin"),
String::from("abcd23"));
println!("{}", p.summary());
}
其他
- 在使用泛型类型参数的
impl
块上使用 trait bound
,我们可以有条件的为实现了特定 trait 的类型来实现方法