Rust简明教程第五章-Trait 特质

时间:2024-07-08 07:57:20

观看B站软件工艺师杨旭的rust教程学习记录,有删减有补充

Trait 特质

  • trait:共同行为,与其他类型共享的功能
  • trait bounds(约束):将泛型类型参数指定为实现了指定行为的类型
  • trait只有方法签名没有具体实现
  • 实现trait类型必须实现其方法
pub trait MyTrait {
    fn method1(&self);
    fn method2(&self, value: u32) -> u32;
}
struct MyStruct;

impl MyTrait for MyStruct {
    //实现trait
    fn method1(&self) {
        println!("方法1");
    }

    fn method2(&self, value: u32) -> u32 {
        println!("方法2和参数:{}", value);
        value * 2
    }
}
fn main() {
    let my_struct = MyStruct;
    my_struct.method1();//方法1
    let result = my_struct.method2(5);//方法2和参数:5
    println!("结果: {}", result);//结果: 10
}

trait bounds约束

  • 实现trait的前提是trait是在本地crate定义的
  • 默认实现的方法可以调用trait中其他方法,即使这些方法没有默认实现
trait MyTrait {
    fn method1(&self) {//method1实现了trait
        println!("调用了 method1");//调用了 method1
        self.method2();
    }
    fn method2(&self);//method2没有实现trait
}
struct MyStruct;
impl MyTrait for MyStruct {
    fn method2(&self) {
        println!("调用了 method2");//调用了 method2
    }
}
fn main() {
    let my_struct = MyStruct;
    my_struct.method1();
}

trait中作为参数

trait MyTrait {
    fn method(&self);
}
struct MyStruct;
impl MyTrait for MyStruct {
    fn method(&self) {
        println!(" 方法");
    }
}
// 使用 `impl trait` 方法
fn perform_action_with_impl_trait(item: impl MyTrait) {
    item.method();
}
// 使用 `trait bound` 方法
fn perform_action_with_trait_bound<T: MyTrait>(item: T) {
    item.method();
}
fn main() {
    let my_struct = MyStruct;

    // 使用 `impl trait` 方法调用函数
    // perform_action_with_impl_trait(my_struct);

    // 使用 `trait bound` 方法调用函数
    perform_action_with_trait_bound(my_struct);
}

where子句指定多个trait bound

//声明trait
trait Display {
    fn display(&self);
}

trait Debug {
    fn debug(&self);
}

trait Clone {
    fn clone(&self);
}
//声明结构体
struct MyStruct1;
struct MyStruct2;
//实现trait方法
impl Display for MyStruct1 {
    fn display(&self) {
        println!("Displaying Trait");
    }
}
impl Debug for MyStruct1 {
    fn debug(&self) {
        println!("Debugging Trait");
    }
}
impl Clone for MyStruct2 {
    fn clone(&self) {
        println!("Clone Trait");
    }
}
impl Debug for MyStruct2 {
    fn debug(&self) {
        println!("Clone Trait");
    }
}
//指定多个trait
fn perform_action<T, U>(item1: T, item2: U)
where
    T: Display + Debug,
    U: Clone + Debug,
{
    item1.display(); // Displaying Trait
    item1.debug(); // Debugging Trait
    item2.clone(); // Clone Trait
}
fn main() {
    let my_struct1 = MyStruct1;
    let my_struct2 = MyStruct2;
    perform_action(my_struct1, my_struct2);
}

实现trait作为返回类型

trait Shape {
    fn area(&self) -> f64;
}

struct Rectangle {
    width: f64,
    height: f64,
}

impl Shape for Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height //返回矩形面积
    }
}

struct Circle {
    radius: f64,
}

impl Shape for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * self.radius.powi(2) //返回圆形面积
    }
}

fn create_shape(is_rectangle: bool) -> Box<dyn Shape> {
    if is_rectangle {
        Box::new(Rectangle {
            width: 5.0,
            height: 3.0,
        })
    } else {
        Box::new(Circle { radius: 2.0 })
    }
}

fn main() {
    let rectangle = create_shape(true);
    let circle = create_shape(false);

    println!("矩形面积: {}", rectangle.area());//矩形面积: 15
    println!("圆形面积: {}", circle.area());//圆形面积: 12.566370614359172
}

有条件的实现方法

trait Printable {
    fn print(&self);
}

struct Number {
    value: i32,
}

impl<T> Printable for T
where
    T: std::fmt::Display,
{
    fn print(&self) {
        println!("Value: {}", self);//Value: Hello, world!
    }
}

fn main() {
    let number = Number { value: 42 };
    // number.print();

    let string = "Hello, world!";
    string.print();//只有实现了std::fmt::Display trait的类型才能实现
}

trait定义关联类型,实现该trait时被具体化

struct MyIterator {
    data: Vec<i32>,
    index: usize,
}
impl Iterator for MyIterator {
    type Item = i32;//具体化
    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.data.len() {
            let item = self.data[self.index];
            self.index += 1;
            Some(item)
        } else {
            None
        }
    }
}
fn main() {
    let my_iterator = MyIterator {
        data: vec![1, 2, 3, 4, 5],
        index: 0,
    };

    for item in my_iterator {
        println!("元素: {}", item);//元素: 1元素: 2元素: 3元素: 4元素: 5
    }
}

balanket implementations 覆盖实现

为满足trait bound的所有类型实现trait

impl<T: Display> ToString for T {//对所有实现两Display的trait实现tostring trait
    // --snip--
}