Introduction to traits in Rust

Mondo Technology Updated on 2024-01-30

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.

Related Pages