Rust Trait

Rust trait 定义了多个类型的共享功能。

Rust traits 促进了类型安全,在编译时防止错误,并且在功能上类似于其他语言中的接口,但有一些区别。


在 Rust 中定义 Trait

我们可以使用 trait 关键字后跟 trait 名称以及构成 trait 的方法来定义 Rust trait。

让我们看看 trait 的语法。

trait TraitName {
    fn method_one(&self, [arguments: argument_type]) -> return_type;
    fn method_two(&mut self, [arguments: argument_type]) -> return_type;
    ...
}

这里,

  • TraitName - trait 的名称。
  • method_one()method_two() - trait 中方法的名称。
  • &self&mut self - 对 self 值的引用。方法可以接受对当前对象的可变或不可变引用,具体取决于它是否需要修改其值。
  • [arguments: argument_type] (可选) - 参数列表,其中每个参数都有一个名称和类型。
  • return_type - 方法返回的类型。

现在,让我们定义一个 trait。

trait MyTrait {
    fn method_one(&self);
    fn method_two(&mut self, arg: i32) -> bool;
}

在这里,我们声明了一个名为 MyTrait 的 trait,其中包含 method_one(&self)method_two(&mut self, arg: i32) -> bool 的方法签名。方法签名描述了实现此 trait 的类型的行为。

一个 trait 可以在其主体中包含多个方法签名,每行一个。Trait 默认不执行任何操作,仅为定义。为了使用 trait,类型需要实现它。


在 Rust 中实现 Trait

要实现 trait,我们使用 impl 关键字。实现 (impl) 块的语法是

impl TraitName for TypeName {
    fn method_one(&self, [arguments: argument_type]) -> return_type {
        // implementation for method_one
    }

    fn method_two(&mut self, [arguments: argument_type]) -> return_type {
        // implementation for method_two
    }

    ...
}

这里,TraitName 是正在实现的 trait 的名称,TypeName 是正在实现该 trait 的类型的名称。

注意: Trait 的实现必须具有与 trait 中的方法相同的签名,包括名称、参数类型和返回类型。

现在,让我们实现 trait。我们将使用 MyTrait 作为 trait,并将 MyStruct 作为我们为其实现 trait 的类型。

trait MyTrait {
    // method signatures
    fn method_one(&self);
    fn method_two(&mut self, arg: i32) -> bool;
}

struct MyStruct {
    value: i32,
}

impl MyTrait for MyStruct { // implementation of method_one fn method_one(&self) { println!("The value is: {}", self.value); } // implementation of method_two fn method_two(&mut self, arg: i32) -> bool { if arg > 0 { self.value += arg; return true; } else { return false; } } }

在此示例中,

  • method_one() 接受对 self 的引用,并打印其 self.value 字段的值。
  • method_two() 接受对 self 的可变引用和类型为 i32 的参数 arg。如果 arg 大于零,我们将 arg 添加到 value 字段并返回 true,否则返回 false

示例:在 Rust 中定义、实现和使用 Trait

// Define a trait Printable
trait Printable {
    fn print(&self);
}

// Define a struct to implement a trait
struct Person {
    name: String,
    age: u32,
}

// Implement trait Printable on struct Person
impl Printable for Person {
    fn print(&self) {
        println!("Person {{ name: {}, age: {} }}", self.name, self.age);
    }
}

// Define another struct to implement a trait
struct Car {
    make: String,
    model: String,
}

// Define trait Printable on struct Car
impl Printable for Car {
    fn print(&self) {
        println!("Car {{ make: {}, model: {} }}", self.make, self.model);
    }
}

// Utility function to print any object that implements the Printable trait
fn print_thing<T: Printable>(thing: &T) {
    thing.print();
}

fn main() {
    // Instantiate Person and Car
    let person = Person { name: "Hari".to_string(), age: 31 };
    let car = Car { make: "Tesla".to_string(), model: "Model X".to_string() };
    
    // Call print_thing with reference of Person and Car
    print_thing(&person);
    print_thing(&car);
}

输出

Person { name: Hari, age: 31 }
Car { make: Tesla, model: Model X }

在此示例中,我们定义了一个 Printable trait,并为两个结构体 PersonCar 实现了它。Printable trait 要求实现者具有名为 print 的方法。

main() 函数中,我们实例化 PersonCar,并将它们传递给 print_thing() 函数。print_thing 是一个泛型函数,它可以接受实现了 Printable trait 的任何对象的引用。

要了解有关 Rust 中泛型的更多信息,请访问 Rust Generics


在 Rust 中 Trait 的默认实现

有时为 trait 中的某些或所有方法提供默认行为会很有用。在定义 Rust trait 时,我们也可以为方法提供默认实现。

例如,

trait MyTrait {
    // method with a default implementation
    fn method_one(&self) {
        println!("Inside method_one");
    }
    
    // method without a default implementation
    fn method_two(&self, arg: i32) -> bool;
}

在这里,method_one()method_one() 主体中有一个 println!() 函数调用,它充当实现 trait MyTrait 的所有类型的默认行为。

但是,method_two() 只定义了方法签名。


Rust 中的 derive 关键字

Rust 中的 derive 关键字用于为类型生成某些 trait 的实现。它可以在 structenum 定义中使用。

我们来看一个例子:

// use derive keyword to generate implementations of Copy and Clone
#[derive(Copy, Clone)] struct MyStruct { value: i32, }
fn main() { let x = MyStruct { value: 10 }; let y = x; println!("x: {:?}", x.value); println!("y: {:?}", y.value); }

输出

x = 10
y = 10

在这里,我们使用 derive 关键字实现了 Rust 标准库中的 CopyClone trait。

Copy trait 允许我们通过简单复制将 x 赋值给 yClone trait 允许我们创建现有实例的精确副本的新实例。

通过使用 derive 关键字,我们可以避免编写实现这些 trait 所需的代码。

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战