侧边栏壁纸
博主头像
喵记博主等级

行动起来,活在当下

  • 累计撰写 18 篇文章
  • 累计创建 4 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Rust(十二):Trait和泛型

张秋平
2024-02-15 / 0 评论 / 0 点赞 / 38 阅读 / 3771 字

Rust 中的Trait和泛型

Trait

  • trai 类似于其它语言中的“接口”或“抽象函数”,它可以为多个不同的类型定义一个共有的抽象方法,也可以用来实现泛型约束

  • trait 中的方法也可以定义默认实现,默认实现的方法可以调用trait中的其它方法,即使这些方法没有默认实现

  • 使用trait的类型也可以重载trait中已经有默认实现的方法;但是无法从方法的重写实现中调用该方法的默认实现

定义一个trait

定义一个trait,这个trait里有两个方法info()say_hello() ,其中say_hello()具有默认实现

// 定义一个 trait, 其中有一个 info 函数来表示输出类型的基本信息
trait Info {
    fn info(&self) {}

    fn say_hello(&self) {
        println!("Hello!");
    }
}

定义使用这个trait的类型

定义两个结构体

struct People {
    name: String,
    age: u8,
}

struct Book {
    name: String,
    author: String,
    price: f32,
}

// 为 People 定义 trait 的实现
impl Info for People {
    fn info(&self) {
        println!("姓名:{}, 年龄:{}", self.name, self.age);
    }

    // 重载 trait 中 say_hello 的默认实现
    fn say_hello(&self) {
        println!("Hello, {}", self.name);
    }
}

// 为 Book 绑定 trait 实现
impl Info for Book {
    fn info(&self) {
        println!("书名:{}, 作者:{}, 单价:{}", self.name, self.author, self.price);
    }
}

简单使用

fn main() {
    let a = People{
        name: String::from("Zhangsan"),
        age: 18,
    };

    let b = Book{
        name: String::from("Rust"),
        author: String::from("unKnown"),
        price: 34.56,
    };

    a.info();
    b.info();

    a.say_hello();  // a 定义了自己的 say_hello 方法实现, 因此将覆盖掉 trait 的默认实现而使用自己定义的实现
    b.say_hello();  // b 没有定义自己的 say_hello 方法实现, 因此使用 trait 默认的实现
}

/* 输出:
姓名:Zhangsan, 年龄:18
书名:Rust, 作者:unKnown, 单价:34.56
Hello, Zhangsan
Hello!
*/

将 trait 作为函数参数的类型使用

定义两个函数,它们的参数类型为实现了 trait 的类型,有如下两种方式为函数的参数指定为 trait 类型,通常在只有一个 trait 的时候更推荐方式二,而在有多个参数每个参数需要实现多个 trait 时更推荐方式三;其实方式一就是方式二的一个语法糖

// 方式一
fn test_fn(a: &impl Info) {
    a.info();
    a.say_hello();
}

// 方式二,如果该参数需要使用多个 trait 则使用 '+' 号进行连接, 如 T: Info + Display
fn test_fn_02<T: Info>(a: &T) {
    a.info();
    a.say_hello();
}

// 方式三, 同样的,如果参数需要满足多个 trait 则使用 '+' 号进行连接
fn test_fn_03<T>(a: &T)
    where T: Info
{
    a.info();
    a.say_hello();
}

使用这个函数:

fn main() {
    let a = People{
        name: String::from("Zhangsan"),
        age: 18,
    };

    let b = Book{
        name: String::from("Rust"),
        author: String::from("unKnown"),
        price: 34.56,
    };

    test_fn_01(&a);
    test_fn_02(&b);
    test_fn_03(&a);
}

/* 输出:
姓名:Zhangsan, 年龄:18
Hello, Zhangsan
书名:Rust, 作者:unKnown, 单价:34.56
Hello!
姓名:Zhangsan, 年龄:18
Hello, Zhangsan
*/

泛型

如下,定义一个求和函数,使其既能满足使用整型作为参数,也能满足使用浮点型作为参数

use std::ops::Add;

fn main() {
    let a = 123;
    let b = 456;

    let m = 123.456;
    let n = 456.789;

    let x = my_sum(a, b);
    let y = my_sum(m, n);

    println!("x = {}, y = {}", x, y);

}

fn my_sum<T: Add<Output = T>>(a: T, b: T) -> T {
    a + b
}

/* 输出:
x = 579, y = 580.245
*/

0

评论区