(done) 速通 rustlings(23) 特性 Traits

特性

特性 Traits 可以为已存在的类型/模块/结构体 添加方法,如下:

rust 复制代码
// The trait `AppendBar` has only one function which appends "Bar" to any object
// implementing this trait.
trait AppendBar {
    fn append_bar(self) -> Self;
}

impl AppendBar for String {
    // TODO: Implement `AppendBar` for the type `String`.
    fn append_bar(mut self) -> Self {
        self.push_str("Bar");
        self
    }
}

上面的代码定义了一个特性叫 AppendBar。随后为类型 String 实现了这个特性(往字符串末尾添加 "Bar")。

完整代码:

rust 复制代码
// The trait `AppendBar` has only one function which appends "Bar" to any object
// implementing this trait.
trait AppendBar {
    fn append_bar(self) -> Self;
}

impl AppendBar for String {
    // TODO: Implement `AppendBar` for the type `String`.
    fn append_bar(mut self) -> Self {
        self.push_str("Bar");
        self
    }
}

fn main() {
    let s = String::from("Foo");
    let s = s.append_bar();
    println!("s: {s}");
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn is_foo_bar() {
        assert_eq!(String::from("Foo").append_bar(), "FooBar");
    }

    #[test]
    fn is_bar_bar() {
        assert_eq!(String::from("").append_bar().append_bar(), "BarBar");
    }
}

更多例子:为 Vec 添加特性

样例代码:

rust 复制代码
trait AppendBar {
    fn append_bar(self) -> Self;
}

impl AppendBar for Vec<String> {
    fn append_bar(mut self) -> Self {
        //        ^^^ this is important
        self.push(String::from("Bar"));
        self
    }
}

特性的默认实现

直接在 trait 花括号内实现的函数属于该特性的默认实现,可以被所有实现该特性的结构体共享。

rust 复制代码
trait Licensed {
    // TODO: Add a default implementation for `licensing_info` so that
    // implementors like the two structs below can share that default behavior
    // without repeating the function.
    // The default license information should be the string "Default license".
    fn licensing_info(&self) -> String {
        "Default license".to_string()
    }
}

struct SomeSoftware {
    version_number: i32,
}

struct OtherSoftware {
    version_number: String,
}

impl Licensed for SomeSoftware {} // Don't edit this line.
impl Licensed for OtherSoftware {} // Don't edit this line.

特性的泛型

实现同一个特性的结构体有点类似于 "拥有同一个父类",如下:

rust 复制代码
trait Licensed {
    fn licensing_info(&self) -> String {
        "Default license".to_string()
    }
}

struct SomeSoftware;
struct OtherSoftware;

impl Licensed for SomeSoftware {}
impl Licensed for OtherSoftware {}

fn compare_license_types(software1: impl Licensed, software2: impl Licensed) -> bool {
    //                              ^^^^^^^^^^^^^             ^^^^^^^^^^^^^
    software1.licensing_info() == software2.licensing_info()
}

可以看到 impl Licensed 被作为了数据类型

若是实现了多个特性,还可以使用 impl trait1 + trait2 作为数据类型,如下:

rust 复制代码
trait SomeTrait {
    fn some_function(&self) -> bool {
        true
    }
}

trait OtherTrait {
    fn other_function(&self) -> bool {
        true
    }
}

struct SomeStruct;
impl SomeTrait for SomeStruct {}
impl OtherTrait for SomeStruct {}

struct OtherStruct;
impl SomeTrait for OtherStruct {}
impl OtherTrait for OtherStruct {}

fn some_func(item: impl SomeTrait + OtherTrait) -> bool {
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    item.some_function() && item.other_function()
}

相关推荐
大卫小东(Sheldon)40 分钟前
小鹤音形词典:一个用 Rust 写的离线编码查询桌面工具
ai·rust
就业发动机1 小时前
我用 Tauri 做了一个约 1.5 MB 的开源屏幕标注工具:MarkerOn
vue.js·rust
2601_954526754 小时前
【硬核架构】打破 IT 与 OT 的数据孤岛!基于 Rust 异步协程的工业 IoT 网关重构,兼谈顶级自动化智能仪表厂家选型指南
物联网·架构·rust
white_ant4 小时前
17- 文本统计/处理工具使用指南
rust·个人开发·tauri
独孤留白5 小时前
Rust 类型转换全景指南 —— 从引用转换到序列化
rust
独孤留白5 小时前
从C到Rust:Trait TryFrom TryInto 可能失败的类型转换
rust
雨师@6 小时前
python通过rust编写组件扩展自己的能力
python·rust
程序员爱钓鱼8 小时前
Rust 切片 Slice 详解:安全访问连续数据
前端·后端·rust
花褪残红青杏小14 小时前
Rust图像处理第20节-PCA 主成分分析:把图片压缩到 3 个数字
rust·webassembly·图形学
脱胎换骨-军哥1 天前
C++/Rust无缝互操作:混合系统新常态
开发语言·c++·rust