• Rust Trait简介


    Rust trait简介

    内容总结自《The Rust Programing Language》

    首先简单说一下泛型:这个基础和C++的模板大概类似,从语法编译层面提供一种接收任意类型的手段,需要知道的是泛型在编译时会进行单态化处理,所以泛型是不会增加运行时负担的。熟悉C++的前提下,泛型应该是看一下就可以很快入门,这里不赘述。

    trait定义

    Rust通过 trait 以一种抽象的方式定义共享的行为。可以使用 trait bounds 指定泛型是任何拥有特定行为的类型,trait就类似其他语言的接口。trait 定义就是一种将方法签名组合起来的方法,目的是定义一个实现某些目的所必需的行为的集合。

    贴一下相干性的概念:(感觉是常识)

    不能为外部类型实现外部 trait。例如,不能在 aggregator crate 中为 Vec 实现 Display trait。这是因为 DisplayVec 都定义于标准库中,它们并不位于 aggregator crate 本地作用域中。这个限制是被称为 相干性coherence) 的程序属性的一部分,或者更具体的说是 孤儿规则orphan rule),其得名于不存在父类型。这条规则确保了其他人编写的代码不会破坏你代码,反之亦然。

    //trait定义的简单例子
    pub trait Summary {
        fn summarize_author(&self) -> String;
    	//trait方法支持默认实现
        fn summarize(&self) -> String {
            format!("(Read more from {}...)", self.summarize_author())
        }
    }
    pub struct Tweet {
        pub username: String,
        pub content: String,
        pub reply: bool,
        pub retweet: bool,
    }
    
    impl Summary for Tweet {
        fn summarize_author(&self) -> String {
            format!("@{}", self.username)
        }
    }
    
    let tweet = Tweet {
        username: String::from("horse_ebooks"),
        content: String::from("of course, as you probably already know, people"),
        reply: false,
        retweet: false,
    };
    
    println!("1 new tweet: {}", tweet.summarize());
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    trait适用场景

    使用 trait 来接受多种不同类型的参数。

    //该函数接收一个trait参数,那么只要是实现(impl)了Summary的类型都是有效参数
    pub fn notify(item: impl Summary) {
        println!("Breaking news! {}", item.summarize());
    }
    
    //trait语法糖 trait bound
    
    //这里强制item1,item2必须是相同的具体类型
    pub fn notify<T: Summary>(item1: T, item2: T) {
    
    //使用+号可以同时实现多个trait
    pub fn notify(item: impl Summary + Display) {}//impl写法
    pub fn notify<T: Summary + Display>(item: T) {}//trait bound写法
    
    //通过where简化trait bound
    //显得杂乱无章
    fn some_function<T: Display + Clone, U: Clone + Debug>(t: T, u: U) -> i32 {}
    //使用where之后好看多了
    fn some_function<T, U>(t: T, u: U) -> i32
        where T: Display + Clone,
              U: Clone + Debug
    {}
    
    //一个使用trait boud编写函数的例子
    fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
        let mut largest = list[0];
    
        for &item in list.iter() {
            if item > largest {
                largest = item;
            }
        }
    
        largest
    }
    
    //使用trait bound有条件的实现
    //通过使用带有 trait bound 的泛型参数的 impl 块,可以有条件地只为那些实现了特定 trait 的类型实现方法。
    //示例中的类型 Pair 总是实现了 new 方法,
    //不过只有那些为 T 类型实现了 PartialOrd trait (来允许比较) 
    //和 Display trait (来启用打印)的 Pair 才会实现 cmp_display 方法:
    #![allow(unused)]
    fn main() {
    use std::fmt::Display;
    
    struct Pair<T> {
        x: T,
        y: T,
    }
    
    impl<T> Pair<T> {
        fn new(x: T, y: T) -> Self {
            Self {
                x,
                y,
            }
        }
    }
    
    impl<T: Display + PartialOrd> Pair<T> {
        fn cmp_display(&self) {
            if self.x >= self.y {
                println!("The largest member is x = {}", self.x);
            } else {
                println!("The largest member is y = {}", self.y);
            }
        }
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69

    trait 和 trait bound 让我们使用泛型类型参数来减少重复,并仍然能够向编译器明确指定泛型类型需要拥有哪些行为。因为我们向编译器提供了 trait bound 信息,它就可以检查代码中所用到的具体类型是否提供了正确的行为。

  • 相关阅读:
    opencv之cv2.findContours和drawContours(python)
    顺序表的C语言实现(静态/动态)
    轻松掌握视频制作技巧:批量分割长视频的详细步骤
    Vue常用但记不住的操作
    论文阅读 - TwiBot-22: Towards Graph-Based Twitter Bot Detection
    Hadoop超详细入门(一)介绍及安装
    Lightroom Classic 2021 v10.4
    【Matplotlib绘制图像大全】(二十二):Matplotlib绘制气泡图
    Django models新增属性后 迁移报错 KeyError,求解
    记录基于scapy构造ClientHello报文的尝试
  • 原文地址:https://blog.csdn.net/weixin_45730130/article/details/128085904