• Rust trait


    Rust trait

    Rust中的trait类似于Java中的接口,定义了一组可以被类型选择实现的“契约”或共享行为,。

    特征定义:

    trait Playable{
        fn play(&self);
        fn pause(){
            println!("Paused");
        }
    }
    

    上述是一个简单trait定义,提供了两个方法,一个用于提供播放功能,一个用于提供暂停功能。

    实现trait:

    struct Audio(String);
    struct Vedio(String);
    impl Playable for Audio {
        fn play(&self) {
            println!("Audio play");
        }
    }
    impl Playable for Vedio {
        fn play(&self) {
            println!("Vedio play");
        }
    }
    

    上述用两个结构体Audio和Vedio分别实现了Playable接口

    或许你已经注意到我们只实现了一个play方法,并没有在“实现”pause方法,其实他们是不同的两种方法。

    trait方法

    trait中可以有两种方法:

    关联方法:

    类似于Java中的静态方法,可以直接类型调用

    实例方法:

    以self/&self/&mut self作为第一个参数的方法,如果没有默认实现需要实现者提供实现,通过实例变量调用

    调用trait方法:

    fn main() {
        let audio=Audio(String::from("audio"));
        audio.play();
        Audio::pause();
        let vedio=Vedio(String::from("vedio"));
        vedio.play();
        Vedio::pause();
    }
    

    输出结果:

    Audio play
    Paused
    Vedio play
    Paused
    

    当然,我们也可以重新实现关联方法:

    impl Playable for Audio {
        fn play(&self) {
            println!("Audio play");
        }
    
        fn pause(){
            println!("Audio Paused");
        }
    }
    

    调用部分代码不变,结果如下:

    Audio play
    Audio Paused
    Vedio play
    Paused
    

    trait 分类

    标记特征

    在std::marker模块定义的特征被称为标记特征,这种特征不包含任何方法,声明时只是提供特征名称和{},例如标准库提供的Copy,Send,Sync

    泛型特征

    特征也可以是泛型的:

    pub trait From<T> {
        fn from(t:T)->Self;
    }
    

    实现:

    #[derive(Copy,Clone)]
    struct A(i32);
    impl From<String> for A{
        fn from(t:String)->Self {
            A(t.len() as i32)
        }
    }
    

    介绍泛型时再具体讲解

    关联类型特征
    trait Foo{
        type Out;
        fn get_value(self)->Self::Out;
    }
    

    这提供了一种比泛型特征更好的选择,因为可以在特征中声明相关类型而不用使用泛型签名

    这里Out由实现trait实现时指定,Self是具体实现类型的别名,Self::Out是关联类型Out的类型,下面是关联类型trait的一个实现:

    #[derive(Copy,Clone)]
    struct A(i32);
    impl Foo for A {
        type Out = i32;
    
        fn get_value(self)->Self::Out {
            self.0
        }
    }
    
    继承特征

    特征也可以在声明中表明它们依赖于其他特征,这被叫做特征继承。

    举例:

    trait Vehicle{
        fn get_price(&self)->u64;
    }
    trait Car:Vehicle{
        fn model(&self)->String;
    }
    

    trait Car 的声明表示它需要依赖trait Vehicle,下面我们来实现它们看看会发生什么:

    struct TeslaRoadster{
        modle:String,
        release_date:u16,
    }
    impl Car for TeslaRoadster {
        fn model(&self)->String {
            todo!()
        }
    }
    

    这乍一看好像没什么错,但是编译会报如下错误:

    显而易见,这表明我们要实现Car的前提是先实现它的依赖trait,即Vehicle,按照编译器提示作出修改:

    struct TeslaRoadster{
        modle:String,
        release_date:u16,
    }
    impl Vehicle for TeslaRoadster {
        fn get_price(&self)->u64 {
            todo!()
        }
    }
    impl Car for TeslaRoadster {
        fn model(&self)->String {
            todo!()
        }
    }
    

    这样就满足了特征继承的要求

    需要注意的是这里的特征继承只是一个习惯性叫法,只是对特征的实现作出了约束,实现一个trait必须要实现它所依赖的trait,更多的是组合的概念,特斯拉是车子,首先他得有轮子属性

  • 相关阅读:
    函数依赖(转)
    C++对象的深拷贝和浅拷贝
    C++临时匿名对象
    C++操作符重载
    C数组和指针
    动态开发入门之Servlet
    数据库的CURD操作 以及经典的sql语句
    如何删除07版word页眉页脚的横线
    数据库的连接查询
    经典面试题 详细解析Java中抽象类和接口的区别
  • 原文地址:https://www.cnblogs.com/yanshaoshuai/p/14407379.html
Copyright © 2020-2023  润新知