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>;
}