Rust的面向对象(五)——面向对象
文章目录
- Rust的面向对象(五)——面向对象
- 面向对象
- 封装
- 继承与多态(特性)
Rust的面向对象(五)——面向对象
从1973年C语言主体完成到1983年C++正式命名,10年的时间,编程理念经历了一次从面向过程到面向对象的蜕变。数据的组织形式也从struct到class得到了升华。自那以后,几乎所有语言的类都是class,相当一部分程序员知道怎么用class却不能准确说出来面向对象是什么。然而,Go和Rust却同时站出来说:“我们不需要class。”顿时,全场静音。
事实上,面向对象的概念早在1967年的Simula语言中就开始提出来了,比C语言的面世还早了6年。可是时至今日,全网也找不到一个权威的面向对象的定义,有的都是用会意的方式来解释什么是面向对象。
相比面向对象抽象的定义而言,面向对象的三要素却是非常具体的,它们是:
- 封装:为了增强安全性和简化编程的复杂性,隐藏对象的属性和实现细节,仅对外公开接口
- 继承:为了提高代码复用率,子类可继承父类的属性和方法
- 多态:为了消除类型之间的耦合关系,提升代码的灵活性,子类可覆盖父类的方法
封装很好理解,就是定义类的属性和方法,并且提供访问级别来控制其它类的对象是否可以访问它们。Rust虽然没有类,但可以使用结构体或枚举来定义属性,并为结构体或枚举附加方法来实现。
而继承是类之间的关系,因为没有类,Rust和Go都没有继承的概念。不过Rust巧妙的用泛型以及泛型的特性实现了一套与继承相类似的代码共享机制。
多态是建立在继承之上的,它允许在使用父类的地方使用子类,Rust的特性也拥有类似的能力。
在学习Rust的面向对象之前,需要充分意识到接下来要学习的东西与你之前认识的世界有着天壤之别,不要被过去的知识所束缚,退一步,进入一个崭新的世界。
学习Rust的面向对象是一个漫长的过程,里面要掌握的知识非常多,我们可以使用下面的路线图来学习Rust的面向对象:
- 创建结构体或枚举
- 为结构体或枚举实现方法
- 为结构体或枚举实现特性
面向对象
通过前面的学习,我意识到Rust面向对象的与众不同,从面向对象的抽象定义讲,Rust是面向对象的,从面向对象的三要素来讲,Rust又不是面向对象的:Rust没有继承,而它又用另外的方法实现了类似继承的代码共享。因此,不能用传统的面向对象的思维来理解Rust。
最后,一起总结一下Rust面向对象的三要素。
封装
前面学习的为结构体或枚举实现方法,就是封装的体现。但这并不全面,封装不仅仅是把方法聚合在一起这么简单。还记不记得C++的封装还有很多信息保护或隐藏的手段:公有、私有、保护甚至友元,哪些类能访问其他类的哪些方法,是学习面向对象最头疼的问题之一。
Rust也同样拥有信息保护或隐藏的手段,但远没有C++那么复杂。它只有两种公有和私有,但只有一个关键字:pub。添加了pub关键字的方法是公有方法,没有添加的就是私有方法。回顾一下之前学习方法时的例子:
struct Rect(i64, i64);impl Rect {fn area(&self) -> i64 {self.0 * self.1}fn perimeter(&self) -> i64 {(self.0 + self.1) * 2}
}fn main() {let rect1 = Rect(20, 30);println!("area: {}", rect1.area());println!("perimeter: {}", rect1.perimeter());
}
Rect有两个方法,area和perimeter都没有pub关键字,那么,它们都是私有的,main之所以可以调用,是因为它们在同一个文件中。如果拆成两个文件,就不能用了。
rect.rs:
struct Rect(i64, i64);impl Rect {fn area(&self) -> i64 {self.0 * self.1}fn perimeter(&self) -> i64 {(self.0 + self.1) * 2}
}
main.rs:
mod rect; // 导入rect模块fn main() {let rect1 = rect::Rect(20, 30);println!("area: {}", rect1.area());println!("perimeter: {}", rect1.perimeter());
}
编译就会出现问题:
error[E0603]: tuple struct constructor `Rect` is private--> src\main.rs:4:23|
4 | let rect1 = rect::Rect(20, 30);| ^^^^ private tuple struct constructor|::: src\rect.rs:1:13|
1 | struct Rect(i64, i64);| -------- a constructor is private if any of the fields is private|
note: the tuple struct constructor `Rect` is defined here--> src\rect.rs:1:1|
1 | struct Rect(i64, i64);| ^^^^^^^^^^^^^^^^^^^^^^error[E0624]: associated function `area` is private--> src\main.rs:6:32|
6 | println!("area: {}", rect1.area());| ^^^^ private associated functionerror[E0624]: associated function `perimeter` is private--> src\main.rs:7:37|
7 | println!("perimeter: {}", rect1.perimeter());| ^^^^^^^^^ private associated functionerror: aborting due to 3 previous errors
问题一共有三个,第一个问题是说Rect结构体的定义是私有的,这也是Rust的特点,如果结构体要被外部使用,也需要定义成公有。第二个和第三个问题是相同的,结构体的方法也需要定义成公有,因此,将rect.rs改为:
pub struct Rect(i64, i64);impl Rect {pub fn area(&self) -> i64 {self.0 * self.1}pub fn perimeter(&self) -> i64 {(self.0 + self.1) * 2}
}
这回该没问题了吧,然并卵:
error[E0603]: tuple struct constructor `Rect` is private--> src\main.rs:4:23|
4 | let rect1 = rect::Rect(20, 30);| ^^^^ private tuple struct constructor|::: src\rect.rs:1:17|
1 | pub struct Rect(i64, i64);| -------- a constructor is private if any of the fields is private|
note: the tuple struct constructor `Rect` is defined here--> src\rect.rs:1:1|
1 | pub struct Rect(i64, i64);| ^^^^^^^^^^^^^^^^^^^^^^^^^^error: aborting due to previous error
编译器又说,Rect的构造器使用的属性是私有的,需要指定为公有:
pub struct Rect(pub i64, pub i64);impl Rect {pub fn area(&self) -> i64 {self.0 * self.1}pub fn perimeter(&self) -> i64 {(self.0 + self.1) * 2}
}
再编译,终于成功了。
继承与多态(特性)
姑且还是使用继承作为标题吧,但Rust是没有继承的,要共享代码,需要使用特性。
多态是对于继承而言的,Rust的多态,也是通过特性来实现的。
一切皆文件是一种linux的文化,无论是真正的文件,还是网络操作,都被看作是文件,因此,我们设计一个linux系统,首先要有一个类文件特性,然后在真正的文件和网络上实现它:
// 定义类文件特性
trait FileSimilar {fn read(&self) -> String;fn write(&mut self, content: &str);
}// 定义文件结构体
struct File {path: String,content: String
}// 实现类文件特性
impl FileSimilar for File {fn read(&self) -> String {self.content.clone()}fn write(&mut self, content: &str) {self.content += content;}
}// 定义网络结构体
struct NetWork {url: String,content: String
}// 实现类文件特性
impl FileSimilar for NetWork {fn read(&self) -> String {self.content.clone()}fn write(&mut self, content: &str) {self.content = String::from(content);}
}fn main() {let mut f = File{path: String::from("d:\\test"), content: String::from("")};f.write("test");println!("{}", f.read());let mut nw = NetWork{url: String::from("127.0.0.1:80"), content: String::from("")};nw.write("test");println!("{}", f.read());
}
这个例子中,File和NetWork都实现了read和write方法,在调用时,自然而然的分别调用各自的实现,不会造成混乱。
Rust的面向对象(五)——面向对象相关推荐
- JavaSE基础知识(五)--面向对象代码实现初步(实现一个简单的类类型代码)
Java SE 是什么,包括哪些内容(五)? 本文内容参考自Java8标准 一.面向对象(代码实现): 首先,在这里我需要说明一个根本性的问题:实际上,面向对象编程包括了两部分,一个是你的编程思想,一 ...
- Dave Python 练习十五 -- 面向对象编程
#encoding=utf-8 ### *************** 面向对象编程 ******************** #*********** Part 1: 面向对象编程 ******** ...
- Python - - 面向对象 - - 初始面向对象
目录 面向过程vs面向对象 初识面向对象 类的相关知识 对象的相关知识 对象之间的交互 类命名空间与对象.实例的命名空间 类的组合用法 初识面向对象小结 面向对象的三大特性 继承 多态 封装 面向对象 ...
- python 完全面向对象_python面向对象实战
一 面向对象的程序设计的由来 二 什么是面向对象的程序设计及为什么要有它 面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条 ...
- python语言不支持面向对象_Python 面向对象(初级篇)
概述面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发"更快更好更强..." 面向 ...
- Python面向对象学习 1 (什么是面向对象,面向对象的应用场景,待更新)
程序设计的三种基本结构: 面向对象,面向过程,函数式编程 1,什么是面向对象编程 面向对象编程是一种编程方式,此编程方式的落地需要使用 "类" 和 "对象" ...
- 【面向对象】面向对象的分析与设计概述
文章目录 分析与设计 结构化方法与面向对象方法 面向对象分析与设计 分析与设计 分析强调对问题的调查 而不是如何确定解决方案. 设计强调的是问题的逻辑解决方案 . 结构化方法与面向对象方法 结构化方法 ...
- 什么是面向过程?什么是面向对象?面向对象的三大基本特征是什么?
一.什么是面向过程? 面向过程是一种以过程为中心的编程思想,其原理就是将问题分解成一个一个详细的步骤,然后通过函数实现每一个步骤,并依次调用. 面向过程我们所关心的是解决一个问题的步骤,举个例子,汽车 ...
- 面向对象,面向对象的优点
面向对象,面向对象的优点 什么是面向对象呢,百度百科的词条解释是这样的 面向对象(Object Oriented)是软件开发方法,一种编程范式.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如 ...
- 什么是面向对象?面向对象的特征?面向对象和面向过程的区别?
什么是面向对象? 面向对象是一种思想,世间万物都可以看做一个对象,这里只讨论面向对象编程(OOP), Java 是一个支持并发.基于类和面向对象的计算机编程语言. 面向对象软件开发具有以下优点: 代码 ...
最新文章
- SCRIPT1028:缺少标识符、字符串或数字 jquery ajax
- 用 eclipse SVN 插件共享项目
- 简谈WP,IOS,Android智能手机OS
- 北斗导航 | 学习PPP和PPP-RTK
- Java并发程序设计(八)设计模式与并发之单例模式
- leetcode 73 矩阵置零 C++ 两种解法
- swift 滑动 iphone解锁_这10个iPhone隐藏功能,我就不信你全知道
- 最近见了几位东半球的顶级技术大拿
- 中国数字墨水行业市场供需与战略研究报告
- mongodb 学习笔记 04 -- 游标、索引
- acs880变频器静态辨识_ACS880变频器PID控制参数设置
- html的reset按钮的作用简单介绍
- wifi辐射知多少【解疑答惑篇】
- matlab simulink 数学符号,MATLAB符号数学
- 传奇世界私服务器端制作,关于内网架设传奇世界私服问题的一些解答
- 单片机24秒倒计时c语言,单片机汇编语言24秒倒计时程序
- 休眠(Hibernate)和睡眠(Sleep)的区别
- final修饰变量、方法、类的作用
- 微信企业付款 ”错误码:NO_AUTH,错误信息:此IP地址不允许调用接口,如有需要请登录微信支付商户平台更改配置“报错的处理办法
- zabbix proxy 的搭建流程【物理机】