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!!!");
}
相关推荐
知产xiao_xin3 小时前
知识产权入门 —— 相关权(邻接权)
经验分享·笔记·知识产权
自小吃多3 小时前
DXF文件导入与PCB板框定义笔记
笔记·嵌入式硬件
q平面人4 小时前
【总工笔记】mindoc平板、桌面端笔记软件,发布到mindoc服务端
rust·tauri·华为平板·mindoc·总工笔记
jike_20265 小时前
iPhone采访录音同时拍现场照片的APP:图片音频同步记录实测
笔记·智能手机·音视频·语音识别
MC皮蛋侠客6 小时前
Tauri 2.x 系列(九):安全模型——Capabilities、Permissions、Scope 与 CSP
rust·tauri
————A6 小时前
Agent 接收用户上传文件
人工智能·笔记·python·状态模式
奔跑的痕迹6 小时前
如何删除引力画报?
笔记
zbyyd6 小时前
Linux 进程间通信学习笔记
linux·笔记·学习
Source.Liu7 小时前
【Dioxus】Windows 环境下 Rust + Dioxus 安装配置笔记
windows·rust·dioxus
知产xiao_xin7 小时前
知识产权入门 —— 版权
经验分享·笔记·知识产权