您的位置 首页 > 德语词汇

trait是什么意思?用法、例句(Rust 特征(Trait))

其实trait是什么意思?用法、例句的问题并不复杂,但是又很多的朋友都不太了解Rust 特征(Trait),因此呢,今天小编就来为大家分享trait是什么意思?用法、例句的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

trait是什么意思?用法、例句(Rust 特征(Trait))

在偏于底层的语言中,在Rust在出现之前,我们除了c++好像没有别的选择。而且c++因为历史问题,会有一定的学习成本,而且难于控制。现在因为有了Rust所以c++也有了压力。

组成我们程序中,通常都是由数据行为所组成,编程多半工作就是用行为操作数据。数据对行为是一种限制,而行为由在改变数据结构。

fnmake_true(input:&str)->String{\nformat!("{}!!",input)\n}\n

定义函数make_true对字符串进行操作,然后返回字符串,这是对数据的操作。我们希望函数是确定性,确定性保证更容易对函数进行测试。

#[derive(Debug)]\nstructFact{\ntext:String\n}\n\nfnmake_true(input:&Fact)->Fact{\nFact{text:format!("{}!!",input.text)}\n}

往往将字符串定义在范围,我们将字符串作为对象Fact的属性,然后make_true接收Fact对象然后对其text属性进行操作。

我们希望方法与数据有一定关系,也就是方法属于数据,或者说想要将方法添加到数据上,在其他语言是method。在rust为结构体添加行为很简单,

implFact{\nfnmake_true(&self)->Fact{\nFact{text:format!("{}!!",self.text)}\n}\n}\n\n\nfnmain(){\n\nletfact=Fact{text:String::from("hello")};\nprintln!("{:#?}",fact.make_true());\n}\n

上面代码大家疑问最多可能就是self,为什么我们需要self

implFact{\nfnmake_true(&mutself){\nself.text.push_str("!!");\n}\n}\n

implFact{\nfnmake_true(mutself)->Fact{\nself.text.push_str("!!");\nself\n}\n}\n\n

letfact=Fact{text:String::from("hello")};\nletfact_1=fact.make_true();\nprintln!("{:#?}",fact_1.text);\n特征定义

trait用于定义与其他类型共享功能,这是一种抽象,类似于其他语言(例如go语言)中的接口。今天将介绍如何创建trait以及其实现和使用,最后会给出基于trait实现日志系统。

\npubtraitGetInformation{\nfnget_title(&self)->&String;\nfnget_course(&self)->u32;\n}\n

使用trait关键字来定义特征,然后在其中定义一系列行为,也就是空方法,需要结构体去实现。

pubstructTut{\npubtitle:String,\npubcourse:u32,\n}\n\nimplGetInformationforTut{\nfnget_title(&self)->&String{\n&self.title\n}\n//u32天然具有copy特征\nfnget_course(&self)->u32{\nself.course\n}\n}\n

定义结构体实现特征GetInformation的get_title这个结构体就具有GetInfomation特征。

fnmain(){\n\nletjs_tut=Tut{title:"vue".to_string(),course:10};\nprintln!("js_tuttitle={}course={}",js_tut.get_title(),js_tut.get_course())\n}\n\n

在go语言我们可以根据行为进行划分类别,只要具有行为结构体就属于某一个按类别进行划分的类别。有时候我们传入结构体,需要具有一定能力。

作为参数输入结构体需要具有一定行为,也就是结构体实现某种特征

fnprint_information(tut:implGetInformation){\nprintln!("title={}",tut.get_title());\nprintln!("age={}",tut.get_course())\n}\n\n\nfnmain(){\n\nletjs_tut=Tut{title:"vue".to_string(),course:10};\n//println!("js_tuttitle={}course={}",js_tut.get_title(),js_tut.get_course())\nprint_information(js_tut);\n\n}\n默认Trait实现

有些时候我们可以通过给出默认方法的实现,也就是给方法提供默认行为。

traitTutInfo{\nfnget_tut_info(&self)->String{\nString::from("suppliedbyzideazone")\n}\n}\n

定义TutInfo特征,然后给行为定义默认行为,如果实现特征TutInfo没有复写get_tut_info方法时就会默认执行TutInfo特征默认提供的行为。

implTutInfoforTut{\n\n//addcodehere\n}\n

letjs_tut_info=js_tut.get_tut_info();\nprintln!("tutinfo={}",js_tut_info);\nTrait边界

trait边界指定泛型是任何拥有特定行为的类型。

fnprint_information_two<T:GetInformation>(tut:T){\nprintln!("title={}",tut.get_title());\nprintln!("age={}",tut.get_course());\n}\n

这里就是使用特征边界(traitbound)来定义函数接受参数需要具有一定约束(要求结构体必须实现某种方法),所以约束就是要求结构体需要具有一定能力。

也可以指定多个特征边界(train_bound),来约束对象具有多个行为。其实语法还是比较好理解,一门新语言带来很多新的特性,但是并不能改变你编程和设计程序能力。只是便于你对程序设计的实现。

traitGetTitle{\nfnget_title(&self)->&String;\n}\n\ntraitGetCourse{\nfnget_course(&self)->u32;\n}\n\nimplGetTitleforTut{\nfnget_title(&self)->&String{\n&self.title\n}\n}\n\nimplGetCourseforTut{\nfnget_course(&self)->u32{\nself.course\n}\n}\n\nfnprint_information_three<T:GetTitle+GetCourse>(tut:T){\nprintln!("title={}",tut.get_title());\nprintln!("age={}",tut.get_course());\n}\n

还有一种特征边界的写法,通过where对泛型进行限制,

fnprint_information_five<T>(tut:T)whereT:GetCourse+GetTitle{\n\nprintln!("title={}",tut.get_title());\nprintln!("age={}",tut.get_course());\n}\n

接下来,也可以特征边界(traitbound)来约束函数的返回值类型。

fnget_tut()->implGetTitle{\nTut{\ntitle:String::from("react"),\ncourse:20\n}\n}\n

这里需要补充一下这里get_tut返回值是trait类型,我们不能通过条件来返回不同都实现GetTitle的不同结构体,这样会报错

letreactTut=get_tut();\nprintln!("titleofreacttut={}",reactTut.get_title());\nTrait对象

在我们所熟悉的面向对象编程语言中,对象包含属性和方法。创建对象便可调用其方法(行为)进行操作。在Rust中,将数据保存在enums或是structs,而行为写作trait里,也就是将数据和行为分开。Trait对象行为更像传统的对象。Trait对象可以包含数据和行为,但是又不同于传统对象。

#[derive(Debug)]\nstructLoggger{\n}\n\nimplLogger{\nfnerror(&self,message:&str){}\nfnwarn(&self,message:&str){}\nfninfo(&self,message:&str){}\nfndebug(&self,message:&str){}\n}\n

上面定义了不同级别的日志输出的方法,分别是error,warn,info和debug。根据日志输出形式又定义不同类型日志输出trait

traitLoggger{\nfnerror(&self,message:&str);\nfnwarn(&self,message:&str);\nfninfo(&self,message:&str);\nfndebug(&self,message:&str);\n}\n\n

#[derive(Debug)]\nstructPrintLogger{\n}\n\nimplLogggerforPrintLogger{\n\nfnerror(&self,message:&str){\nprintln!("ERROR:{}",message)\n}\nfnwarn(&self,message:&str){\nprintln!("ERROR:{}",message)\n}\nfninfo(&self,message:&str){\nprintln!("ERROR:{}",message)\n}\nfndebug(&self,message:&str){\nprintln!("ERROR:{}",message)\n}\n}\n

?这里我们定义特征Logger,让不同日志输出类型都去实现Logger特征,这样他们就是不同类型却具有相同行为的类别

pubfnlog_example(logger:&Logger){\nlogger.info("runingexamplecode..");\nlogger.info("doneexamplecode");\n}\n

这里&Logger也称为Trait对象,在Trait对象中包含

在Trait对象是包含一个指向堆上数据指针,以这种形式来保存数据,当堆上值大小变化不会影响到Trait对象,这样更利于分配内存给对象。

logger.info("runingexamplecode..");\n

在上面语句编译器会先从vtable中加载info函数地址,然调用到info函数的地址。看整个过程,可能会担心效率,这样做会不会影响程序的性能。

好了,文章到这里就结束啦,如果本次分享的trait是什么意思?用法、例句和Rust 特征(Trait)问题对您有所帮助,还望关注下本站哦!

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023