Traits in Rust

What is Triat in Rust

Interface/class in Rust(declared with keyword trait) having Virtual Functions(not pure Virtual) declared or defined inside it. These functions are implemented(overridden) on type.

Declaration & Definition

Trait is implemented for particular types. Eg: add_to_db() function is overridden for Employee, Contractor Type.

User Defined Traits

Trait Declaration

pub trait T {
    // No need to add pub in front of function
    // Trait methods are public by default
    fn add(&self);
    // Functions can be defined with default implementation 
    fn test(&self) {
     println!("test()");
    }
}        

Type on which trait is defined

pub struct S {
    pub x: i32,
    pub y: i32,
}        

Trait Definition

//impl triat for type
impl T for S {
    fn add(&self) {
        println!("Sum: {}", self.x + self.y);
    }
}
fn main() {
    let a = S {
        x: 1,
        y: 2,
    };
    a.add();
}        

Passing trait as argument to function

// trait T defined above
pub fn fun(t: &impl T) {
    t.test();
}
fn main() {
    let a = S {
        x: 1,
        y: 2,
    };
    fun(&a);
}
$ cargo run
test()        

Returning trait from function

// trait T defined above
// This function can return struct of type S also
pub fn ret_trait() -> impl T {
    S {
        x: 1,
        y: 2,
    }
}        

Trait Bound

These are generic functions(templates) but must implement one or more traits, which ensures that the type provides certain behavior or methods


// Trait(T) is defined above
            //< type: TraitName> (var: type)
pub fn fun1 <t: T> (item: &t) {
    item.test();
}
$ cargo run
test()        

Using + //Friend Function

There can be a function which takes 2 or more traits(virtual function).

pub fn test <T: Trait1 + Trait2> (param: &T) {
OR
pub fn test (param: &(impl Trait1 + Trait2) {        

Using where clause //Friend Function

pub fn test <T: Trait1 + Triat2, U: Triat2 + Triat2>(t: &T, u: &U) -> i32 {
OR
pub fn test <T, U>(t: &T, u: &U) -> i32
    where T: Triat2 + Triat2
            U: Triat2 + Triat3
{        

Rust Library Provided Traits

Copy & Clone Traits

Both are used for duplicating the values.

All types that implement Copy must also implement Clone, but the reverse is not true

// COPY TRAIT CODE
// Only Copy triat is used, but to use
// Copy, we need to derive Clone
#[derive(Copy, Clone)]
pub struct S {
    x : i32,
    y : i32,
}
fn main() {
    let a = S {
        x: 1,
        y: 5,
    };
    let b = a;
    println!("b = {}, {}", b.x, b.y);
}


// CLONE TRAIT CODE
#[derive(Clone)]
pub struct S {
    x : Vec,
}
fn main() {
    let a = S {
        x: vec![1,2,3],
    };
    let b = a;
    for i in 0..b.x.len() {
        println!("{} ", b.x[i]);
    }
}        

Default trait

Used to give default value

#[derive(Default)]

Rust to provide Default implementation

#[derive(Default)]
pub struct Test {
    a : i32,
}
fn main() {
    let test1: Test = Default::default();
    println!("{}",test1.a);
}
$ cargo run
0        //0 is initialized by rust system        

Default value by user

User overrides the default() function provided by Default Trait


pub struct test {
    a : i32,
}
impl Default for test{
    fn default() -> Self {
        Self {
            a: 48,
        }
    }
}
fn main() {
    let test1: Test = Default::default();
    println!("{}",test1.a);             //48
}        

drop trait

Custom code within the destructor. When a value is no longer needed, Rust runs a “destructor” on that value, but if we want to perform some task in destructor, use drop trait.

#[derive(Default)]
pub struct S {
    x : i32,
}
impl Drop for S {
    fn drop(&mut self){
        println!("Dropping");
    }
}
fn main() {
    {
        let s:S = Default::default();
        println!("{}", s.x);
    }
    println!("After scope");
}
$ cargo run
0
Dropping
After scope        

future trait

future is a “asynchronous value” that may not have finished computing yet. Thread waits on future to become available. These are similar to epoll(), not similar to poll() or select().

pub trait Future {
    //The type of value produced on completion.
    type Output;                 
    
    /*Description:
        This method resolves future into a final value. This is aync method does not block if value is not ready
        Returns:
        Poll::Pending if the future is not ready. 
        Poll::Ready(val) with the result val of this future if it finished successfully.
        */
    fn poll(self: Pin <&mut Self>, cx: &mut Context <'_>) -> Poll <Self::Output>;
}        

要查看或添加评论,请登录

社区洞察

其他会员也浏览了