Trait in Rust is a feature of the Rust language that describes each type of functionality it can provide. It is similar to the characteristics of interfaces defined in other languages, such as the interface of j**a go c++. A feature is a method of grouping method signatures to define a set of behaviors. Trait is by usingtraitkeywords.
100 help plan
Syntax: A trait is declared via the trait keyword (collectively referred to as interfaces or behaviors). Within curly brackets, a method signature is declared to describe the behavior of the type that implements the interface.
trait
fn main()
let a = **
let **area = a.area();
println!("The area of the triangle is: {}",**area);
In the example above, a feature named hasarea is declared, which contains a declaration of the area() function. hasarea is implemented on the ** type. By using a struct instance (i.e., aarea()) to simply call the area() function.
interface as a parameter
Interfaces can also be used as parameters for many different types.
The example above implements the hasarea feature and contains the definition of the area() function. We can define the calculate area() function that calls the area() function, and use an instance of the type that implements the hasarea feature to call the area() function.
Example: fn calculate area(item : impl hasarea).
println!("The area of the triangle is: {}item.")area())
Boundaries of generic interface functions
Interfaces are useful because they describe the behavior of different methods. However, generic functions do not respect this constraint. Let's understand this through a simple scenario:
fn calculate_area( item : t)
println!(?area of a **is {}item.area())
In the above case, the Rust compiler throws an "error, no method named type t found". If we bind the feature to a generic t, we can resolve the following error:
fn calculate_area (item : t)
println!("area of a **is {}",item.area())
In the above case, it means that "t can be any type that implements the hasarea feature". The rust compiler knows that any type that implements the hasarea feature will have an area() function.
Let's take a look at a simple example:
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);
The output can be run by yourself, and in the example above, the calculate area() function is a generic function on "t".
Rust implements the rules for the interface
There are two limitations to implementing a trait:
If the feature is not defined in your scope, it cannot be implemented on any data type.
The characteristics we are implementing must be defined by us.
Use the "+" action.
Use the where condition.
Boundaries can be written using the where condition. A statement that appears before the opening parentheses.
A where clause can also be applied to any type.
When and where to use the where clause, it makes grammar more expressive than normal grammar.
Here are a few examples to illustrate each of the feature rules:
use::std::fs::file;
fn main()
let mut f = file::create("hello.txt");
let str = "j**atpoint";
let result = f.write(str);
In the above case, the Rust compiler throws an error that says "There is no method named 'write';Discover "ASuse::std::fs::file;The namespace does not contain a write() method. Therefore, we need:Use the write feature to eliminate compilation errors
If we definehasareainterface, then we can implement this interface for the i32 type. However, we can't implement what Rust defines for i32 typestostringInterface behavior, as it is not defined in our types and interfacestostring
If we want to bind multiple properties, we can use the + operator, as in the following example:
use std::fmt::;
fn compare_prints(t: &t) ,t);
println!("display: '{}'", t);
fn main()
In the above example, by using the + operation, the two interfaces of debug and display are implemented, and type t is bound
Default method
If a method is already defined, you can add a default method to the trait definition.
trait sample
fn a(&self);
fn b(&self)
In the above case, the default method is added to the interface definition. We can also override the default method.
Scenario examples. 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();
In the example above, the behavior of the b() function is defined in the trait and is overridden. Therefore, we can conclude that we can rewrite the methods defined in the trait.
Inheritance
An interface method derived from another interface is calledInheritance。Sometimes, it is necessary to implement a method that needs to implement another interface. If we want to derive the "B" interface from the "A" interface, the interface derived from the other interface is called inheritance. Sometimes, it is necessary to implement a method that needs to implement another interface. If we want to export the "B" interface from the "A" interface, it will be written as follows:
trait b : a;
Example: Trait 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();
In the example above, we implement the "b" feature. Therefore, it also needs to implement the "a" feature. If we don't implement the "A" feature, then the Rust compiler will throw an error.