Rust Trait

Rust 第16节 Trait

Trait 告诉编译器

某种类型具有那些并且可以与其他类型共享的功能

它的本质就是
不同类型具有的相同行为

声明一个trait

关键字 trait;只有方法签名,没有方法实现

rust 复制代码
pub trait Animal {// trait 的声明,一个trait中可以有多个方法
    fn say(&self) -> String;
		fn func1(&self){};
		fn func2(&self){};
}

实现该Trait 的类型,必须提供具体的方法实现;

即 类型要和Trait进行关联;

例如:

rust 复制代码
pub struct Dog {
    pub name : String,
    pub age : i32,
}

impl Animal for Dog {   //将该类型使用trait
    fn say(&self) -> String {
        format!("my name is {}",self.name)
    }
}

其他类型也可以跟这个Trait进行关联

rust 复制代码
pub struct Cat {
    pub name : String,
    pub age : i32,
    pub fun : String,
}

impl Animal for Cat {
    fn say(&self) -> String {
        format!("my name is {},my age is {}",self.name,self.age)
    }

}

调用

rust 复制代码
    let d1 = Dog{
        name : "Tom".to_string(),
        age : 3,
    };

    let c1 = Cat {
        name : "Goj".to_string(),
        age : 2,
        fun : "xx".to_string(),
    };

    println!("{}",d1.say());
    println!("{}",c1.say());

注意:

这个类型 或者 这个 trait是本地定义的;

无法为外部类型 实现外部trait

Trait 的默认实现方法

rust 复制代码
pub trait Animal {// trait 的声明,一个trait中可以有多个方法
    fn say(&self) -> String;
    fn hello(&self) {  //默认实现的方法
        println!("hello everyone!!");
    }
    fn goodbye(&self){
        println!("{},goodbye !!",self.say());  //默认实现的方法可以调用其他方法,即使这个方法不是默认实现的方法
    }  
}

对于跟Trait关联的类型;可以对默认函数进行重新定义,即重构

rust 复制代码
impl Animal for Cat {
    fn say(&self) -> String {
        format!("my name is {},my age is {}",self.name,self.age)
    }
    fn hello(&self) { //在这个类型中,对默认方法进行了重构
        println!("hello everyone ,i'm {}",self.name);
    }
}

也可以不改变,使用默认方法

rust 复制代码
impl Animal for Dog {   //将该类型使用trait
    fn say(&self) -> String {
        format!("my name is {}",self.name)
    }
    //在这个类型中,没有对trait的hello方法进行重构,所以使用的是默认的实现
}

Trait 作为参数

期望这个函数的参数是有Animal trait功能的类型

方法1 impl Trait 语法 使用于简单类型

rust 复制代码
pub fn speek(item : impl Animal) {
    println!("this is me, {}",item.say());
}
rust 复制代码
   speek(c1);
   speek(d1);

方法2 Trait bound 语法

直译就是Trait 约束,适用于比较复杂的场景

rust 复制代码
pub fn speek_v2<T: Animal>(item : T) {
    println!("V2: {}",item.say());
}
//复杂场景
pub fn speek_v3<T:Animal>(item1 : T,item2 : T) {
    println!("v3: {},{}",item1.say(),item2.say());
}
rust 复制代码
    speek_v2(c1);
    speek_v2(d1);
		speek_v3(d1, d2);

需要参数同时支持多个Trait

期望这个函数的参数是同时支持两个trait功能的类型

使用 + 号,来表示同时支持多个trait

rust 复制代码
pub fn two_speek(item : impl Animal + Funcitons) {
    println!("{}",item.say());
    item.my_function();
}

trait bound

rust 复制代码
pub fn two_speek_v2<T:Animal + Funcitons>(item : T ) {
    println!("{}",item.say());
    item.my_function();
}

当有更复杂场景时,使用where约束

rust 复制代码
pub fn speek_v4<T : Animal,U : Animal + Funcitons>(item1 : T,item2 : U) {
    item1.goodbye();
    item2.my_function();
}

where 约束

rust 复制代码
pub fn speek_v5<T,U>(item1 : T,item2 : U) 
where
    T : Animal,
    U : Animal + Funcitons,
{
    item1.goodbye();
    item2.my_function();
}

Trait 作为返回值

注意点,这个函数只能返回某一种具体的类型;返回可能得不同的类型,编译器会报错

rust 复制代码
pub fn create_animal(s : &str) -> impl Animal{
    Dog {
        name : String::from("s"),
        age : 12,
    }
}

泛型 加 Trait

定义一个泛型结构体

rust 复制代码
struct Pair<T> {
    x : T,
    y : T,
}

针对所有泛型T,定义一个方法:

rust 复制代码
impl<T> Pair<T> {
    fn new(x :T ,y : T) -> Self {
        Self {x , y}
    }  //这个泛型结构体有一个new 函数
}

针对满足要求的Trait类型,定义一个方法:

rust 复制代码
impl<T : Display + PartialOrd> Pair<T> {  
// 这里对泛型结构体中的 cmp_display() 方法进行了约束,只有类型T 满足 Display 和 PartialOrd 两个Trait时,才能有这个方法。
    fn cmp_display(&self) {
        if self.x >= self.y {
            println!("largest member is {}",self.x);
        } else {
            println!("largest member is {}",self.y);
        }
    }
}

覆盖约束

满足某一约束条件然后去实现另一Trait 的行为叫覆盖约束

例如to_string()方法

3.to_string();

数字3 可以调用to_string()方法,

是由于 3 有 display方法,

所有有display方法的类型,都被实现了 to_string 方法

相关推荐
q567315234 分钟前
Java使用Selenium反爬虫优化方案
java·开发语言·分布式·爬虫·selenium
kaikaile19958 分钟前
解密Spring Boot:深入理解条件装配与条件注解
java·spring boot·spring
守护者17023 分钟前
JAVA学习-练习试用Java实现“一个词频统计工具 :读取文本文件,统计并输出每个单词的频率”
java·学习
bing_15834 分钟前
Spring Boot 中ConditionalOnClass、ConditionalOnMissingBean 注解详解
java·spring boot·后端
ergdfhgerty36 分钟前
斐讯N1部署Armbian与CasaOS实现远程存储管理
java·docker
勤奋的知更鸟1 小时前
Java性能测试工具列举
java·开发语言·测试工具
三目君1 小时前
SpringMVC异步处理Servlet
java·spring·servlet·tomcat·mvc
用户0595661192091 小时前
Java 基础篇必背综合知识点总结包含新技术应用及实操指南
java·后端
fie88891 小时前
Spring MVC扩展与SSM框架整合
java·spring·mvc
不太可爱的叶某人1 小时前
【学习笔记】深入理解Java虚拟机学习笔记——第3章 垃圾收集器与内存分配策略
java·笔记·学习