您现在的位置是:首页 >技术杂谈 >RUST 每日一省:trait种类网站首页技术杂谈

RUST 每日一省:trait种类

许汶强 2023-07-13 04:00:02
简介RUST 每日一省:trait种类

       trait的基本形式,很简单,但这只是trait的冰山一角。当你开始接触大型代码库中的trait时,将会遇到它的多种形式。种类繁多有助于我们完成复杂问题的建模。下面我们一次介绍其他形式的trait,以便了解何时需要使用它们。

标准trait 


这是trait定义的最简单形式。我们它作为trait定义进行了阐述:

trait Foo {
    fn foo();
}

标准库中的一个示例是 Default 特征,它主要是针对可以使用默认值初始化的类型实现的。

泛型trait


trait也可以是泛型。当用户希望为多种类型实现trait的情况下非常有用:

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

这样的例子是 From<T>,它们允许从某种类型转换为类型 T,反之亦然。例如下例,我们给Number实现了From<i32> trait,这意味着,所有的i32,都可以通过Number::from()函数转化为Number。

#[derive(Debug)]
struct Number {
    value: i32,
}

impl From<i32> for Number {
    fn from(item: i32) -> Self {
        Number { value: item }
    }
}

fn main() {
    let num = Number::from(30);
    println!("My number is {:?}", num);
}

关联类型trait

trait Contains<A, B> {
    fn contains(&self, _: &A, _: &B) -> bool; 
    fn first(&self) -> i32; 
    fn last(&self) -> i32; 
}

//关联类型
trait Contains {
    type A;
    type B;

    fn contains(&self, _: &Self::A, _: &Self::B) -> bool;
}

        这是泛型trait的更好选择,因为它们能够在trait中声明相关类型。它们具有较少的类型签名,其优点在于,在实际的编程中,它们允许用户一次性声明关联类型,并在任何特征方法或函数中使用 Self::A 作为返回类型或参数类型。这消除了类型的冗余声明,与泛型trait的情况类似。关联类型trait的最佳用例之一是 Iterator 特征, 它用于迭代自定义类型的值。 在后边文章, 我们将会深入介探讨一下。

marker  trait


        在 std::marker 模块中定义的特征被称为marker  trait。这种trait不包含任何方法,声明时只是提供特征名称和空的函数体。其实我们之前介绍copy和clone时,就介绍了copy其实就是 marker trait。
        除了Copy,标准库中的示例还有Send、 Sync。它们被称为marker  trait,因为它们用于简单地将类型标记为属于特定的组群,以获得一定程度的编译期保障。标准库中的两个这样的示例是 Send 和 Sync 特征,它们在适当的时候由语言为大多数类型自动实现,并确定哪些值可以安全地发送和跨线程共享。我们将在后续文章对它们进行详细介绍。

父trait


Rust 没有“继承”,但是你可以将一个 trait 定义为另一个 trait 的超集(即父 trait)。例如:

trait Person {
    fn name(&self) -> String;
}

// Person 是 Student 的父 trait。
// 实现 Student 需要你也 impl 了 Person。
trait Student: Person {
    fn university(&self) -> String;
}

        在上述代码片段中,我们声明了一个trait Student,它依赖于父级trait Person。在 Student的定义中,要求用户在为类型实现 Student特征时必须为 Person trait提供实现。标准库中的这样一个示例是 Copy trait,它要求类型必须实现 Clone trait。

派生trait

通过 #[derive] ,编译器能够提供某些 trait 的基本实现。如果需要更复杂的行为,这些 trait 也可以手动实现。

下面是标准库中一些可以自动派生的 trait:

  • 比较 trait: Eq,PartialEq,Ord,PartialOrd 
  • Clone, 用来从 &T 创建副本 T
  • Copy,使类型具有 “复制语义”(copy semantics)而非 “移动语义”(move semantics)。
  • Hash,从 &T 计算哈希值(hash)。
  • Default, 创建数据类型的一个空实例。
  • Debug,使用 {:?} formatter 来格式化一个值。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。