Trait 本意是特性,特质,特性等等,其实重要指人的性格特性。不明白为什么rust的创造者不使用feature这样单词。
如作者所言:
Note: Traits are similar to a feature often called interfaces in other languages, although with some differences.
特性类似于别的语言的接口,但和接口还是有一些区别的。
为了便于行文,本文把Trait翻译为特质。
我查了一些资料,可以确认这句话基本上是对的。不对的在那里了?此处先不聊了。 总之特质在大部分情况下可以当做接口即可。
但是不能把特质称为接口,由于接口仅仅是特质的一个功能,它另有别的作用。
本文的内容重要都是为了通用类型服务,前面讲了许多接口特质的内容。
从本章开始,可以看到越来越多奇奇怪怪的语法,虽然我已经学过不少语言,但Rust绝对是此中的奇葩!
一、如何定义一个接口特质
所谓接口特质,即作为接口使用的特质。
就一个步骤:- pub trait Work{
- fn design(&self);
- fn code(&self);
- fn test(&self);
- }
复制代码
1.pub修饰符可选
2.一个接口特质中可以定义多个方法
这和大部分语言差不多。
二、为结构体实现一个接口特质
2.1基本实现
实现一个接口特质也很简朴,使用impl语法:
trait Summary { fn summarize(&self) -> String; fn get_content(&self) -> &String; fn is_empty(&self) -> bool { self.get_content().is_empty() }}struct Tweet { pub username: String, pub content: String, pub reply: bool, pub retweet: bool, pub time: String}
impl Summary for Tweet { fn summarize(&self) -> String { format!("{}: {} -- {}", self.username, self.content,self.time) } fn get_content(&self) -> &String { &self.content }}
fn main(){ let tweet = Tweet { username: String::from("勒布朗.詹姆斯"), content: String::from("我,要退网!"), reply: false, retweet: false, time: String::from("2024-11-21 05:01:01") }; println!("{}", tweet.summarize());} 几个注意事项:
1.当实现一个接口特质的时候,必须实现这个接口特质中的所有方法,不能只有一部分
2.不能越界实现别的单位包中的接口特质。例如在单位包a存在接口特质 Ta,那么无法在单位包b中实现Ta
如果违反了,会提示:only traits defined in the current crate can be implemented for types defined outside of the crate
define and implement a trait or new type instead
3.如果接口特质T在当前单位包,那么无论对象(结构体、枚举等)O位于那里,那么都可以为O实现T
4.在同一个单位包内,你不能在差别模块为同个对象实现多次接口特质
以上第2条并不是普适的。rust的一些特质是位于标准库中,但答应你在本身的模块中实现这些接口特质,典型的是Display
2.2 默认实现
和java一样(从J8开始),rust也提供了默认实现,只不过java把接口搞得更加复杂一些。- trait Summary {
- fn summarize(&self) -> String;
- fn get_content(&self) -> &String;
- fn is_empty(&self) -> bool {
- self.get_content().is_empty()
- }
- }
复制代码 方法is_empty就是默认的实现。这样在实今世码中,不需要提供is_empty有关的代码,也可以正常使用:- trait Summary {
- fn summarize(&self) -> String;
- fn get_content(&self) -> &String;
- fn is_empty(&self) -> bool {
- self.get_content().is_empty()
- }
- }struct NewsArticle { pub headline: String, pub location: String, pub author: String, pub content: String}impl Summary for NewsArticle { fn summarize(&self) -> String { format!("{}, by {} ({}) \n {}", self.headline, self.author, self.location,self.content) } fn get_content(&self) -> &String { &self.content }}fn main(){ let news= NewsArticle { headline: String::from("英雄纪念碑"), location: String::from("中国北京"), author: String::from("新华社记者m--泽--东"), content: String::from("由此上溯到一千八百四十年,从那时起,为了反对内外敌人, 争取民族独立和人民自由幸福,在历次斗争中捐躯的人民英雄们永垂不朽!") }; println!("{}", news.summarize()); println!("{}", news.is_empty()); }
复制代码
默认方法是否可以覆盖了?可以的,这个和java也一样:- impl Summary for NewsArticle {
- fn summarize(&self) -> String {
- format!("{}, by {} ({}) \n {}", self.headline, self.author, self.location,self.content)
- }
- fn get_content(&self) -> &String {
- &self.content
- }
- fn is_empty(&self) -> bool {
- println!("{}", self.content.len());
- self.content.len()<1000
- }
- }
复制代码
四、返回接口特质
和别的语言类似,但是这个有个题目:rust编译器只把返回的当作接口特质,而不是当作具体的对象(结构体或者枚举)。
以是,如果没有类似别的语言的强制转换,或者编译器支持,企图把返回的接口特质当作某个对象,那是不可的。- fn print(article:&impl Summary){
- println!("{}", article.get_content());
- }
复制代码
上例中,为什么my_tube.vol会陈诉非常,是由于rust编译器的逻辑只认为my_tube是一个接口特质,以是my_tube不能调用Tube的属性/方法,但是
my_tube可以调用Brush的具体方法。
五、资助实现通用类型函数/方法
前面的一堆内容就是为了两个目的:如何定义和实现接口特质;如何在通用类型方法中限定参数的范围。
“如何定义和实现”基本上都明白了,现在就示例下如何实现“通用类型参数限定范围”。
方式是:使用接口特质
语法: 或者,或者也可以使用where字句- /**
- * 使用<T:t>的方式,是impl trait的方式的正规形式。
- * 即print_normal是print的正规形式
- */
- fn print_normal<T:Summary>(article:&T){
- println!("使用<T:t>的方式:{}", article.get_content());
- }
复制代码
六、小结
- 接口特质是特质的一个部分,不能把特质翻译为接口
- 定义接口特质还是比较简朴的。可以在一个接口特质中定义多个方法。
- 不能在当前单位包中实现在别的单位包中定义的接口特质。但是存在例外情况,例如一些rust位于标准库中的接口特质;一个单位包内,不能在差别模块为一个接口特质,一个对象做n次实现
- 接口特质的方法可以有默认实现;默认实现的方法可以被覆盖
- 在方法中可以使用接口特质作为参数。有两种方式:impl,标准。前者不会强制所有参数同个类型,后者会
- 还可以使用where字句来限定参数的接口特质。
- 某个参数如果要绑定(限定)多个接口,可以使用+符号
- 接口特质的出现,使得定义参数,方法变得更加灵活,也更加复杂
- 函数/方法可以返回接口特质,但如果没有特别措施,不能把返回的效果当作具体类型使用。编译器只会把返回效果当值接口特质,即使你在方法体中明确返回的类型。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |