Rust 学习笔记:面向对象语言的特点

Rust 学习笔记:面向对象语言的特点

在编程社区中,对于一门语言必须具备哪些特性才能被认为是面向对象的,并没有达成共识。

面向对象语言具有某些共同的特征,即对象、封装和继承。让我们看看这些特征的含义以及 Rust 是否支持它们。

对象包含数据和行为

《设计模式:可重用面向对象软件的元素》一书是这样定义 OOP 的:

面向对象程序是由对象组成的。对象将数据和对该数据进行操作的过程打包。这些过程通常称为方法或操作。

使用这个定义,Rust 是面向对象的:结构体和枚举具有数据,而 impl 块提供结构体和枚举的方法。尽管带方法的结构体和枚举不称为对象,但它们提供了相同的功能。

封装隐藏了实现细节

与 OOP 相关的另一个方面是封装的思想,这意味着使用该对象的代码无法访问对象的实现细节。因此,与对象交互的唯一方法是通过它的公共 API。使用对象的代码不应该能够进入对象的内部并直接更改数据或行为。这使程序员能够更改和重构对象的内部结构,而无需更改使用该对象的代码。

我们可以使用 pub 关键字来决定代码中的哪些模块、类型、函数和方法应该是公共的,而默认情况下,其他的都是私有的。

例如,我们可以定义一个结构体 AveragedCollection,它有一个包含 i32 值的数组的字段。该结构体还可以有一个字段,包含向量中值的平均值,这意味着当任何人需要它时,不必根据需要计算平均值。换句话说, AveragedCollection 将为我们缓存计算出的平均值。

AveragedCollection 结构体的定义:

pub struct AveragedCollection {
    list: Vec<i32>,
    average: f64,
}

该结构体被标记为 pub,以便其他代码可以使用它,但结构体中的字段仍然是私有的。

我们希望确保每当从列表中添加或删除值时,平均值也会更新。我们通过在结构体上实现 add、remove 和 average 方法来实现这一点:

impl AveragedCollection {
    pub fn add(&mut self, value: i32) {
        self.list.push(value);
        self.update_average();
    }

    pub fn remove(&mut self) -> Option<i32> {
        let result = self.list.pop();
        match result {
            Some(value) => {
                self.update_average();
                Some(value)
            }
            None => None,
        }
    }

    pub fn average(&self) -> f64 {
        self.average
    }

    fn update_average(&mut self) {
        let total: i32 = self.list.iter().sum();
        self.average = total as f64 / self.list.len() as f64;
    }
}

我们将 list 和 average 字段保留为私有,公共方法 add、remove 和 average 是访问或修改 AveragedCollection 实例中的数据的唯一方法。当使用 add 方法将项添加到列表中或使用 remove 方法删除项时,每个项的实现都会调用私有的 update_average 方法,该方法也会处理平均字段的更新。average 方法返回 average 字段中的值,允许外部代码读取平均值,但不能修改它。

如果封装是一种语言被认为是面向对象的必要方面,那么 Rust 就满足了这个要求。对代码的不同部分使用 pub 或不使用 pub 的选项支持对实现细节进行封装。

作为类型系统和代码共享的继承

继承是一种机制,对象可以从另一个对象的定义中继承元素,从而获得父对象的数据和行为,而不必重新定义它们。

如果一种语言必须具有继承才能是面向对象的,那么 Rust 就不是这样的语言。如果不使用宏,就无法定义继承父结构的字段和方法实现的结构。

选择继承有两个主要原因。

一种是代码重用:为一种类型实现特定的行为,继承使能够为另一种类型重用该实现。在 Rust 代码中,你可以使用默认的 trait 方法实现以有限的方式做到这一点。

pub trait Summary {
    fn summarize(&self) -> String {
        String::from("(Read more...)")
    }
}

我们在 Summary trait 上添加了一个 summarize 方法的默认实现。任何实现 Summary trait 的类型都可以在其上使用 summarize 方法,而无需任何进一步的代码。这类似于父类具有方法的实现,继承子类也具有该方法的实现。当我们实现 Summary trait 时,我们也可以覆盖 summarize 方法的默认实现,这类似于子类覆盖从父类继承的方法的实现。

使用继承的另一个原因与类型系统有关:使子类型能够在与父类型相同的位置使用。这也称为多态性,这意味着如果多个对象共享某些特征,则可以在运行时相互替换。Rust 使用泛型来抽象不同可能的类型和 trait 约束,以对这些类型必须提供的内容施加约束。这有时被称为有界参数多态性。

在许多编程语言中,继承作为一种编程设计解决方案最近已经不受欢迎了,因为它经常冒着共享不必要的代码的风险。子类不应该总是共享父类的所有特征,但继承时会这样做。这可能会使程序设计的灵活性降低。它还引入了在子类上调用没有意义的方法或由于方法不适用于子类而导致错误的可能性。此外,一些语言只允许单继承(意味着子类只能继承一个类),这进一步限制了程序设计的灵活性。

由于这些原因,Rust 采用了使用 trait 对象而不是继承的不同方法。

【电能质量扰动】基于ML和DWT的电能质量扰动分类方法研究(Matlab实现)内容概要:本文研究了一种基于机器学习(ML)和离散小波变换(DWT)的电能质量扰动分类方法,并提供了Matlab实现方案。首先利用DWT对电能质量信号进行多尺度分解,提取信号的时频域特征,有效捕捉电压暂降、暂升、中断、谐波、闪变等常见扰动的关键信息;随后结合机器学习分类器(如SVM、BP神经网络等)对提取的特征进行训练与分类,实现对不同类型扰动的自动识别与准确区分。该方法充分发挥DWT在信号去噪与特征提取方面的优势,结合ML强大的模式识别能力,提升了分类精度与鲁棒性,具有较强的实用价值。; 适合人群:电气工程、自动化、电力系统及其自动化等相关专业的研究生、科研人员及从事电能质量监测与分析的工程技术人员;具备一定的信号处理基础和Matlab编程能力者更佳。; 使用场景及目标:①应用于智能电网中的电能质量在线监测系统,实现扰动类型的自动识别;②作为高校或科研机构在信号处理、模式识别、电力系统分析等课程的教学案例或科研实验平台;③目标是提高电能质量扰动分类的准确性与效率,为后续的电能治理与设备保护提供决策依据。; 阅读建议:建议读者结合Matlab代码深入理解DWT的实现过程与特征提取步骤,重点关注小波基选择、分解层数设定及特征向量构造对分类性能的影响,并尝试对比不同机器学习模型的分类效果,以全面掌握该方法的核心技术要点。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值