RUST中的trait是什么?

注:本篇文章全是由我本人通过学习所感悟的内容,所以不能保证是绝对正确的,如果有发现我文章的错误,麻烦请指出我的错误让我能明白我自己错在了哪里,希望大家一起进步。

trait

trait是什么?我先举个例子,在RUST中有非常多的数据类型,i32、u32、string、结构体和枚举等数据类型,而有的数据类型可以直接使用println!("{}", 变量);输出,我们前面了解到只有实现了display这个trait的数据类型才能被输出,如果没有则不行,你发现没这里面主要涉及到的就是数据类型,而trait本质就是为不同的数据类型实现相同的抽象功能。下面我们开始实战举例。下面是一个实例,我们定义了三个结构体及一个trait,而观察程序我们为bob和tom实现了一个attack的trait,这是两个类型,而这两个类型都有一个共同attack,这就是trait在不同的类型实现一个相同的功能,这个功能可以自定义,但是一定要满足trait中的签名,而我们直接在trait中定义的则是默认实现,就像tom中我们并没写具体的内容,而是使用的默认的trait中的内容。下面来开始正式内容把。

rust 复制代码
trait attack {
    fn can_attack(&self) {
        println!("我能攻击");
    }
}
impl attack for Bob {
    fn can_attack(&self) {
        println!("Bob能攻击");
    }
}

impl attack for Tom {
}

struct Bob {
    name: String,
    attack: bool,
}

struct Tom {
    name: String,
    attack: bool,
}

struct Xiaohong {
    name: String,
    attack: bool,
}

fn main() {
    let Bob = Bob {
        name: "Bob".to_string(),
        attack: true,
    };
    let Tom = Tom {
        name: "Tom".to_string(),
        attack: true,
    };
    let Xiaohong = Xiaohong {
        name: "Tom".to_string(),
        attack: false,
    };
    Bob.can_attack();
    Tom.can_attack();
}

//输出
Bob能攻击
我能攻击

为类型实现trait

前面说了,trait是为类型服务的,所以我们下面来拆分上面的代码演示如何为类型实现一个trait。看这个例子就可以发现,实现trait的方式其实很简单,就是impl trait的名字 for 类型的名字 {}然后在里面定义trait的方法就可以实现了,也可以在定义trait的时候直接书写一个完整的函数这样它可以默认使用。

rust 复制代码
//这里我们定义了一个结构体,也就是一个类型。
struct Bob {
    name: String,
    attack: bool,
}
//这里我们定义了一个trait并实现了can_attack方法。
trait attack {
    fn can_attack(&self) {
        println!("我能攻击");
    }
}
//这里我们为Bob类型实现了trait。
impl attack for Bob {
    fn can_attack(&self) {
        println!("Bob能攻击");
    }
}

孤儿原则

孤儿原则是什么,要为一个类型实现一个 trait,这个 trait 或这个类型必须至少有一个是在当前 crate 中定义的。为什么要这样写呢?如果两个都不在当前crate可能存在编译器并不知道你要使用那个trait或那个类型。

默认实现

以《为类型实现trait》的例子举例,当我们在trait中的函数默认定义了内容,这就是默认实现。

rust 复制代码
//这里我们定义了一个trait并实现了can_attack方法。
trait attack {
    fn can_attack(&self) {
        println!("我能攻击");
    }
}

trait约束

trait约束,什么叫trait约束呢,在函数的参数列表或返回值中,我们想定义一个参数,而我们想这个参数是实现了某个或多个trait的,这就叫trait约束。

trait作为参数

下面是一个很简单的例子,当我们想传递的参数是实现了attack的类型,我们可以直接使用impl trait名,来指定。

rust 复制代码
fn iambob(me: &impl attack) {
    println!("I am Bob!!!");
}

+号约束

+号可以在我们想指定一个参数同时实现了多种trait的情况下使用,下面我们有定义了一个fly trait,而我们想传的参数同时满足了attack和fly,我们就可以这样表示(impl trait1 + trait2),举一反三哈可以多+几个。

rust 复制代码
trait attack {
    fn can_attack(&self) {
        println!("我能攻击");
    }
}

trait fly {
    fn can_fly(&self) {
        println!("我会飞哦");
    }
}

impl fly for Bob {}

impl attack for Bob {
    fn can_attack(&self) {
        println!("Bob能攻击");
    }
}

fn iambob(me: &(impl attack + fly)) {
    println!("I am Bob!!!");
}

泛型约束

下面是另一个例子,用于泛型来约束参数,其实看一眼明白了<T: trait1 + trait2>,相反可以只是先一个或更多,自己举一反三把。

rust 复制代码
trait attack {
    fn can_attack(&self) {
        println!("我能攻击");
    }
}

trait fly {
    fn can_fly(&self) {
        println!("我会飞哦");
    }
}

impl fly for Bob {}

impl attack for Bob {
    fn can_attack(&self) {
        println!("Bob能攻击");
    }
}

fn iambob<T: attack + fly>(me: T) {
    println!("I am Bob!!!");
}

where简写

where是为了在约束很多trait的情况下让格式更美观。直接看实例吧,泛型T实现了attack+fly,语法就是在定义返回值之后的位置

where

T: trait1 + trait2,

其他泛型:其他trait,

rust 复制代码
fn iambob<T>(me: &T)
where
    T: attack + fly,
{
    println!("I am Bob!!!");
}
相关推荐
ab12376815 分钟前
Spring Integration 完整笔记 + 和 spring-integration-mqtt、Paho、EMQX 的关系
java·笔记·spring
ACP广源盛1392462567333 分钟前
Type-C 扩展坞方案选型笔记|国产 DP1.2 转 HDMI2.0 桥接芯片 GSV2201D@ACP 评估
开发语言·笔记·硬件架构·硬件工程·hdmi·国产芯片
旖旎夜光38 分钟前
【LangGraph实战】LangGraph 学习笔记(四):持久化——从线程记忆到跨会话长期记忆
人工智能·笔记·python·学习·ai编程·langgraph
kdxiaojie1 小时前
MPU6050学习
笔记·学习·mpu6050
geovindu1 小时前
rust: Borg Pattern(续)
开发语言·后端·设计模式·rust·博格模式
qq_2842740512 小时前
机械原理笔记:平面机构自由度计算(复合铰链、局部自由度、虚约束)与四杆机构入门(含考点)
笔记·学习·平面·自动化·制造
qq_2842740513 小时前
数控铣床与加工中心笔记:铣刀与刀柄系统、G54试切对刀、镜像加工指令、孔加工工艺(钻扩铰镗)与固定循环G73/G83/G81/G76/G87/G84
笔记·学习·自动化·制造
Titan202414 小时前
MySQL访问个人学习笔记
笔记·学习·mysql
深圳老胡15 小时前
STM32CubeMX 生成 CMake 工程,用 VSCode 编译与调试的完整流程
笔记·stm32·单片机·代码规范
坤坤子吖16 小时前
C++智能指针:RAII、shared_ptr与内存泄漏
开发语言·c++·笔记·学习