Rust 中的 Trait 是 Rust 语言的一个特性,它描述了它可以提供的每种类型的功能。 它类似于其他语言中定义的接口的特征,例如 j**a go c++ 的接口。 功能是对方法签名进行分组以定义一组行为的方法。 特征是使用trait关键字。
100 帮助计划
语法:特征是通过 trait 关键字声明的(统称为接口或行为)。 在大括号内,声明了一个方法签名,用于描述实现接口的类型的行为。
trait
fn main()
let a = **
let **area = a.area();
println!("三角形的面积为:{}",**area);
在上面的示例中,声明了一个名为 hasarea 的功能,其中包含 area() 函数的声明。 hasarea 是在 ** 类型上实现的。 通过使用 struct 实例(即area()) 来简单地调用 area() 函数。
接口作为参数
接口还可以用作许多不同类型的参数。
上面的示例实现了 hasarea 功能,并包含 area() 函数的定义。 我们可以定义调用 area() 函数的 calculate area() 函数,并使用实现 hasarea 功能的类型的实例来调用 area() 函数。
示例:fn calculate area(item : impl hasarea)。
println!(“三角形的面积为:{}item.”)area())
泛型接口函数的边界
接口非常有用,因为它们描述了不同方法的行为。 但是,泛型函数不遵循此约束。 让我们通过一个简单的场景来理解这一点:
fn calculate_area( item : t)
println!(?area of a **is {}item.area())
在上述情况下,Rust 编译器抛出一个“错误,没有找到名为 t 类型的方法”。 如果我们将该功能绑定到泛型 t,我们可以解决以下错误:
fn calculate_area (item : t)
println!("area of a **is {}",item.area())
在上面的例子中,这意味着“t 可以是实现 hasarea 功能的任何类型”。 rust 编译器知道任何实现 hasarea 特性的类型都会有一个 area() 函数。
让我们看一个简单的例子:
trait hasarea
fn area(&self)->f64;
struct **
base : f64,
height : f64,
impl hasarea for **
fn area(&self)->f64
struct square
side : f64,
impl hasarea for square
fn area(&self)->f64
fn calculate_area(item : t)
println!("area is : ",item.area())
fn main()
let a = **
let b = square;
calculate_area(a);
calculate_area(b);
输出可以自己运行,在上面的示例中,calculate area() 函数是 “t” 上的通用函数。
Rust 实现了接口的规则
实现特征有两个限制:
如果未在作用域中定义该功能,则无法在任何数据类型上实现该功能。
我们正在实施的特征必须由我们来定义。
使用“+”操作。
使用 where 条件。
可以使用 where 条件编写边界。 出现在左括号之前的语句。
where 子句也可以应用于任何类型。
何时何地使用 where 子句,它使语法比普通语法更具表现力。
下面是一些示例来说明每个功能规则:
use::std::fs::file;
fn main()
let mut f = file::create("hello.txt");
let str = "j**atpoint";
let result = f.write(str);
在上述情况下,Rust 编译器抛出一个错误,指出“没有名为'write'的方法;发现“ASuse::std::fs::file;命名空间不包含 write() 方法。 因此,我们需要:使用写入功能消除编译错误
如果我们定义hasarea接口,那么我们可以为 i32 类型实现这个接口。 但是,我们无法实现 Rust 为 i32 类型定义的内容tostring接口行为,因为它未在我们的类型和接口中定义tostring
如果我们想绑定多个属性,我们可以使用 + 运算符,如下例所示:
use std::fmt::;
fn compare_prints(t: &t) ,t);
println!("display: '{}'", t);
fn main()
在上面的例子中,通过使用 + 操作,实现了 debug 和 display 这两个接口,并绑定了 t 类型
默认方法
如果已定义方法,则可以将默认方法添加到特征定义中。
trait sample
fn a(&self);
fn b(&self)
在上述情况下,默认方法将添加到接口定义中。 我们还可以覆盖默认方法。
方案示例。 trait sample
fn a(&self);
fn b(&self)
struct example
a:i32,b:i32,impl sample for example
fn a(&self),self.a);
fn b(&self),self.b);
fn main()
let r = example;
r.a();
r.b();
在上面的示例中,b() 函数的行为在 trait 中定义并被覆盖。 因此,我们可以得出结论,我们可以重写 trait 中定义的方法。
遗产
从另一个接口派生的接口方法称为遗产。有时,需要实现一个需要实现另一个接口的方法。 如果我们想从“A”接口派生出“B”接口,那么从另一个接口派生的接口称为继承。 有时,需要实现一个需要实现另一个接口的方法。 如果我们想从“A”接口导出“B”接口,会写成如下:
trait b : a;
示例:性状 A
fn f(&self);
trait b : a
fn t(&self);
struct example
first : string,second : string,impl a for example
fn f(&self),self.first);
impl b for example,self.second);
fn main()
let s = example;
s.f();
s.t();
在上面的示例中,我们实现了“b”功能。 因此,它还需要实现“a”功能。 如果我们没有实现 “A” 功能,那么 Rust 编译器将抛出错误。