• 【一起学Rust | 设计模式】习惯语法——默认特质、集合智能指针、析构函数



    前言

    Rust 不是传统的面向对象编程语言,它的所有特性,使其独一无二。因此,学习特定于Rust的设计模式是必要的。本系列文章为作者学习《Rust设计模式》的学习笔记以及自己的见解。

    本期文章主要介绍Rust设计模式中的习惯语法中的

    • 默认特质
    • 集合智能指针
    • 析构函数

    默认特质:Rust在开发中,不能每处都要求实现new方法,为了解决这个问题而实现Default特质,除此以外,还可以与其他的容器一同使用。

    集合智能指针:使用Deref特质可以将集合变为智能指针,提供拥有和借用的数据视图。

    析构函数:Rust没有提供无论函数如何退出,都将执行的代码。但是,可以使用对象的析构函数来运行必须在退出之前运行的代码。


    一、默认特质

    在Rust中,许多类型都有一个构造函数,然而这是特定于某种类型的。Rust并没有强制指定每个类型都必须有一个new方法作为构造函数。为了实现这个需求,Rust提供了Default特质,并且可以与其他容器一起使用。

    注意:一些容器已经在合适的地方实现的Default特质。

    像Cow、Box或Arc这样的单元素容器不仅可以为包含的默认类型实现默认值,还可以自动 #[derive(Default)]为所有字段都实现它的结构,因此实现默认值的类型越多,它就越有用。

    另一方面,构造函数可以接受多个参数,而default()方法不能。甚至可以有多个具有不同名称的构造函数,但每个类型只能有一个默认实现。

    以下是一个例子

    use std::{path::PathBuf, time::Duration};
    
    // 导出默认值
    #[derive(Default, Debug, PartialEq)]
    struct MyConfiguration {
        // 选项默认为“None”
        output: Option<PathBuf>,
        // 默认空向量
        search_path: Vec<PathBuf>,
        // 持续时间默认为0
        timeout: Duration,
        // 布尔值默认为Flase
        check: bool,
    }
    
    impl MyConfiguration {
        // 在这添加setter
    }
    
    fn main() {
        // 构建一个拥有默认值的新实例
        let mut conf = MyConfiguration::default();
        // 做一些处理操作
        conf.check = true;
        println!("conf = {:#?}", conf);
            
        // 部分初始化创建实例
        let conf1 = MyConfiguration {
            check: true,
            ..Default::default()
        };
        assert_eq!(conf, conf1);
    }
    
    
    • 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

    二、集合智能指针

    使用Deref特质可以将集合变为智能指针,提供拥有和借用的数据视图。以下是一个使用的例子。

    use std::ops::Deref;
    
    struct Vec<T> {
        data: RawVec<T>,
        //..
    }
    
    impl<T> Deref for Vec<T> {
        type Target = [T];
    
        fn deref(&self) -> &[T] {
            //..
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Vect 是拥有T的集合,&[T]是借用T的集合,为Vec实现Deref特质,将允许&Vec到&[T]的隐式解引用>

    就像String和&str,可以参考一下。

    所有权和借用是Rust语言的关键方面。为了提供良好的用户体验,数据结构必须适当考虑这些语义。当实现拥有其数据的数据结构时,提供该数据的借用视图允许更灵活的API。

    大多数方法只能为借用的视图实现,然后它们可以隐式地用于所属视图。让客户在借用或取得数据所有权之间进行选择。

    注意:边界检查时不考虑仅通过解引用可用的方法和特性,因此使用此模式的数据结构的通用编程可能会变得复杂(请参见Borrow和AsRef特性等)。

    三、析构函数

    Rust没有提供无论函数如何退出,都将执行的代码。但是,可以使用对象的析构函数来运行必须在退出之前运行的代码。

    以下是使用的例子

    fn bar() -> Result<(), ()> {
        // 这些不是必须要在函数中定义的,也可以在其他地方定义
        struct Foo;
    
        // 为Foo实现析构函数
        impl Drop for Foo {
            fn drop(&mut self) {
                println!("exit");
            }
        }
    
        // _exit的dtor将在退出函数“bar”时运行。
        let _exit = Foo;
        // 用?操作符隐式的返回
        baz()?;
        // 正常返回
        Ok(())
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    如果一个函数有多个返回点,那么在退出时执行代码会变得困难和重复(因此容易出现错误)。这在由于宏而导致返回是隐式的情况下尤其如此。常见的情况是?运算符,如果结果为Err,则返回,但如果结果为Ok,则继续?被用作异常处理机制,但与Java不同(Java最终实现了),无法调度代码在正常和异常情况下运行。Panic也会提前退出函数。

    析构函数中的代码将(几乎)始终运行处理Panic、早期返回等。


    总结

    以上就是本期文章的所有内容,介绍了Rust设计模式中的习惯语法中的三个部分

    • 默认特质
    • 集合智能指针
    • 析构函数

    通过本期内容,希望你能够对Rust开发能有更加深入的了解。

  • 相关阅读:
    pygame 入门实例教程 1 - 复古方块赛车游戏
    前端获取文件后缀名
    QT+Python人脸表情特征识别
    34.0、C语言——C语言预处理(2) - 预编译指令
    深度学习第四课——卷积神经网络(week 2)
    Web3 游戏周报(3.24-3.30)
    矿产行业集中采购管理系统:强化供应链采购把控水平,助推矿企数字化建设
    千万别再学python编程了?编程没用了?马上就要被淘汰啦?
    基于Java毕业设计大学生旅游拼团网站源码+系统+mysql+lw文档+部署软件
    【FPGA教程案例27】通过Verilog实现双口RAM乒乓结构
  • 原文地址:https://blog.csdn.net/weixin_47754149/article/details/126594054