一、前言
本文主要详解Rust中Trait
这个概念,之所以为它单开一个章节,就是因为它非常的重要。
如果与其它语言类比来看,这个Trait
类似于Java
中的接口,C++
中的纯虚类,但却又不完全相同。
因为rust中没有类的概念,trait
作用的是结构体、乃至枚举。
二、初识Trait
trait
这个单词,本意为特征,在代码中的含义就是,让某个结构拥有某个特征。
比如我们之所以能用println!
这个宏打印出String
中的字符串,就是因为String
实现了一个叫做display
的特征。
标准库提供了很多基本的trait
,比如还有复制(copy
),克隆(clone
),调试(debug
),默认值(Default
)等等等等。
本章会对这些常见的trait
做出基本介绍,并学习如何写出与使用一个属于自己的trait
。
如下就是一个使用标准库Display
这个trait
的实例:
struct Stu {
name: String,
age: u32,
id: String,
}
fn main() {
let s = Stu {
name: String::from("www.kucoding.com"),
age: 100,
id: String::from("10010"),
};
println!("{}", s); //错误,Stu这个结构没有实现Display这个trait,所以无法打印
}
上面的代码,我自定义了一个结构体Stu
,并让其创建了一个变量s
,然后我直接用println!
这个宏打印它,是会报错的:
因为它现在还没有实现Display
这个trait
,所以该宏不知道该怎么打印它。
所以下面我们就让其实现一下这个Display
:
use std::fmt;
struct Stu{ /*省略*/ }
impl fmt::Display for Stu {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
return write!(f, "Name: {}, Age: {}, Id: {}", self.name, self.age,self.id);
}
}
fn main() {
let s=Stu{/*省略*/};
println!("{}", s); //正确,Stu这个结构实现了Display这个trait,所以可以打印
}
上面的代码中我省略了部分代码,让其看起来更加简洁,由于Display
这个trait
在标准库std::fmt
中,所以我们首先需要将其引入进来
use std::fmt;
库在rust
中被称为crate
,两者基本等价,就是换了个名字,使用的方式就是用use
关键字进行引入,标准crate为std
,然后fmt
这个crate又在std
里面,所以用两个:
来拿出它。
这类似于C++中的命名空间,比如using std::string;
,就类似于rust中的use std:fmt;
,而C++中的using namespace std
就类似于rust中的use std::*
,也就是让std
内所有内容都可用。
为这个结构体实现trait
的方式很简单,与前面介绍的为结构体绑定方法所用到的关键字一致,都是impl
,不同之处在于,方法是你随意为结构体绑定的,你可以在其中写任何方法:
impl Stu {
/*
可以写任何方法
*/
}
而如果要实现一个trait
,你必须写这个trait
内部已经写好的方法:
impl fmt::Display for Stu {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
return write!(f, "Name: {}, Age: {}, Id: {}", self.name, self.age,self.id);
}
}
这里的impl fmt::Display for Stu
意思就是为Stu
实现fmt::Display
这个Trait
,而这个Trait中就有一个叫做fmt
的函数,格式如下: