(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()
}

相关推荐
doiito14 小时前
【Agent Harness】Gliding Horse 设计细节 -- 不跟风开发自己的AI Agent
架构·rust·agent
doiito16 小时前
【Agent Harness】Gliding Horse 核心设计理念,不跟风开发自己的AI Agent
ai·rust·架构设计·系统设计·ai agent
花褪残红青杏小1 天前
Rust图像处理第6节- 均值模糊 & 中值模糊:3×3 邻域的两种经典玩法
rust·webassembly·图形学
子兮曰1 天前
前端工具链的「Rust 化」:一场没有赢家的军备竞赛?
前端·后端·rust
星栈1 天前
写 Dioxus Demo 不难,难的是把它写成项目
前端·rust·前端框架
mCell1 天前
【锐评】桌面端技术营销:别拿跑分当工程判断
前端·rust·electron
武子康2 天前
调查研究-201 Rust 里的 dev build 和 release build:为什么同一份代码性能差这么多?
后端·架构·rust
doiito2 天前
【Agent Harness】Gliding Horse 的 L2 作战地图:让多 Agent 协作从“摸黑”变成“透明”
ai·rust·架构设计·系统设计·ai agent
星栈2 天前
我用 Rust + Dioxus 做了个全栈跨平台笔记应用:再把新建、编辑和交付补上
前端·rust·前端框架
独孤留白3 天前
从C到Rust:基本类型 C 的隐式不确定 vs Rust 的显式确定
rust