当前位置: 首页 > article >正文

【Rust自学】17.1. Rust的面向对象的编程特性

喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
请添加图片描述

17.1.0. 什么是面向对象的编程特性

面向对象编程(Object-oriented programming,简称OOP)是一种程序建模方法。对象作为编程概念在编程语言Simula中引入。这些对象影响了Alan Kay(他领导了世界上世界上第一个现代窗口计算机桌面的设计和开发)的编程架构,其中对象相互传递消息。为了描述这种架构,他在 1967 年创造了面向对象编程这个术语。

核心概念

  1. 对象(Object)

    • 程序的基本单位,包含属性(状态)和行为(操作)。
  2. 类(Class)

    • 对象的模板,定义了属性和行为。
  3. 封装(Encapsulation)

    • 将数据和操作绑定在一起,隐藏内部细节,通过接口与外部交互。
  4. 继承(Inheritance)

    • 子类继承父类的属性和行为,提高代码重用性。
  5. 多态(Polymorphism)

    • 相同的接口表现出不同的行为,包括方法重载和重写。
  6. 抽象(Abstraction)

    • 只关注必要部分,忽略复杂实现,通过类或接口提供高层次设计。

面向对象编程的优势

  1. 模块化和可维护性:代码易于维护和扩展。
  2. 代码重用性:通过继承和抽象减少重复代码。
  3. 易于扩展:新功能可轻松添加。
  4. 现实建模:贴近现实世界概念。
  5. 数据安全性:通过封装保护数据,增强安全性。

17.1.1. Rust的面对对象编程特点

对于一种语言必须具备哪些特性才能被视为面向对象,编程社区尚未达成共识。 Rust 受到许多编程范式的影响,包括 OOP。OOP通常包括对象、封装和继承等特性。

面对对象编程有很多种定义,而这些定义有很多是相互矛盾的。其中有一些定义能够把Rust划为面对对象编程的语言,而另外一部分定义则不这样认为。

在第13章中我们说过了Rust函数式编程的特性,但它既不是传统的面向对象编程语言,也不是纯函数式编程语言,而是一个多范式编程语言,它结合了函数式编程和面向对象编程的一些特点。

对象包含数据和行为

Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides(这四人通俗地被称为“设计模式四人帮”)所著的"Design Patterns: Elements of Reusable Object-Oriented Software"(《设计模式:可重用面向对象软件的元素》)一书是一本面向对象的目录面向设计模式。它这样定义 OOP:

*Object-oriented programs are made up of objects. An object packages both data and the procedures that operate on that data. The procedures are typically called methods or operations. *
面向对象的程序是由对象组成的。对象封装了数据和操作该数据的过程。这些过程通常称为方法操作

基于这个定义,Rust是面向对象的:structenum包含数据,impl块为之提供了方法。但在Rust里带有方法的structenum并没有称之为对象。

17.1.2. 封装

封装指的是调用对象外部的代码无法直接访问对象内部的实现细节,唯一可以与对象进行交互的方法就是通过它公开的API。

Rust通过pub关键字实现了决定代码中哪些模块、类型、函数或者是方法是公开的。而默认情况下它们都是私有的。

看个例子:

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

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;
    }
}

该结构体被标记为pub以便其他代码可以使用它,但该结构中的字段仍然是私有的。因为我们希望确保每当在列表中添加或删除值时,平均值也会更新。直接给字段改值做不到这一点,所以不能让用户能够修改其字段值。我们通过在结构体上实现addremoveaverage方法来实现。

17.1.3. 继承

继承是指使对象可以沿用另外一个对象的数据与行为,且无需重复定义相关的代码。Rust并不支持这个特性

通常使用继承的原因是代码复用多态

  • 针对代码复用,Rust提供了默认trait方法来进行代码共享。在trait中某个方法有默认实现,那么任何实现了这个trait的类型就会自动拥有这个方法。这和面向对象很类似,在面向对象语言中,父类中实现的方法就可以被继承它的子类拥有。当实现某个trait时,还可以覆盖trait的默认实现,这类似于子类覆盖从父类继承的方法的实现。

  • 多态指期望某个类型能够被应用在需要父类型的地方,换句话说,就是如果一些对象拥有某些共同的特征,那么这些对象就可以在运行时相互替换。Rust通过泛型和trait bound(trait约束)实现了这一点:泛型使得逻辑可以更好的脱离于实际的数据类型,并使用trait bound来决定能使用此逻辑的类型必须提供的某些具体特性,这一技术也称为限定参数多态化(bounded parametric)

现在其实很多语言都不使用继承作为内置的程序设计方案了。因为它经常面临共享过多代码的风险。子类不应该总是共享其父类的所有特征,但可以通过继承来实现。这会降低程序设计的灵活性。它还引入了在子类上调用没有意义或导致错误的方法的可能性,因为这些方法不适用于子类。此外,有些语言只允许单继承(即子类只能从一个类继承),这进一步限制了程序设计的灵活性。


http://www.kler.cn/a/525103.html

相关文章:

  • 前端-Rollup
  • [论文总结] 深度学习在农业领域应用论文笔记14
  • C++ 中用于控制输出格式的操纵符——setw 、setfill、setprecision、fixed
  • Java中的泛型
  • 【C++】特殊类设计、单例模式与类型转换
  • 开源 OA 办公系统
  • EtherCAT主站IGH-- 20 -- IGH之fsm_pdo_entry.h/c文件解析
  • 【重生之我在学习C语言编译与链接详解】
  • ue5笔记(2)
  • OSCP:发送钓鱼电子邮件执行客户端攻击
  • Java面试题2025-并发编程进阶(线程池和并发容器类)
  • DeepSeek:硅谷AI格局的拐点?
  • 基于STM32的自主行驶无人小车教学
  • ping命令详解Type 8和0 或者Type 3
  • 提升RAG效果:为何 JSON 格式远胜 Markdown?
  • SQL注入漏洞之高阶手法 宽字节注入以及编码解释 以及堆叠注入原理说明
  • LeetCode:96.不同的二叉搜索树
  • Vue 3 中的 toRef 与 toRefs:使用与案例解析
  • Deepseek技术浅析(一)
  • 单细胞-第四节 多样本数据分析,下游画图
  • Helm Chart 详解:从入门到精通
  • nodeJS 系统学习-章节4-回调函数
  • 图片上传实现图片预览的功能
  • 浏览器同源策略:从“源”到安全限制的全面解析
  • 【力扣每日一题】存在重复元素 II 解题思路
  • C ++ 1