开发者学堂课程【Go 语言核心编程 - 面向对象、文件、单元测试、反射、TCP 编程:面向对象编程-封装介绍】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/626/detail/9689
面向对象编程-封装介绍
内容简介:
一、面向对象编程三大特性
二、封装
一、 面向对象编程三大特性
基本介绍:传统的面向对象编程语言有三个特性:继承、封装和多态,Golang 里面也有这三个特性,只是它的实现方式和传统的 OOP 不一样,因为 Golang 的设计者做了很多简化,在 Golang 面向对象编程时不要总是参照传统的 OOP 语言去对照,即在学 Golang 面向对象编程时不要和传统语言去比较。
二、封装
1. 封装的介绍
封装( encapsulation )就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其他包只有通过被授权的操作(方法),才能对字段进行操作。当有一个字段叫 name 或者 salary (薪水),且此薪水并不希望是公开的,可以把此字段做成私有的,即将首字母小写,首字母小写后对字段提供一个公开的方法,让别人去操作,这个就叫封装,封装的概念和别的编程语言是一样的,总体来说核心是字段和对字段的操作封装在一起,此为封装的特性。例如:对电视机的操作,电视机的音量调大只需通过遥控器按钮调大就可以,但是电视机内部的结构并不需要我们去管理。这个好比将来对字段的操作,只需要调查字段的方法便可以完成,即对外提供一个操作的方法,就会有方法去帮我们完成,注意此方法需自己去写,这个和对电视机的操作是一个道理,对比计算机的操作,这便是一个典型的封装。
2. 封装的理解和好处
(1)隐藏实现细节
(2)可以对数据进行验证,保证安全合理(Age)
例如:以 Age 为字段
Type Person struct {
Age int
}
假设要设置一个年龄,人尽皆知人的年龄是在一个范围的,目前世界上最大年龄估计在130岁左右,最大不会超过150岁,假设有人在给年龄编程时设置200岁,这是不合理的,于是可以通过对数据进行验证的方法去控制这件事,只有在数据合理的情况下才能将数值设置进去,或修改成功,这时封装便会起到作用。
又例如:
//取款
func (account *Account) WithDraw(money float64,pwd string) {
//看下输入密码是否正确
if pwd != account.Pwd {
fmt.Println(“你输入的密码不正确”)
return
}
//看看取款金额是否正确
if money <= 0 || money > account.Balance {
fmt.Println(“你输入的金额不正确”)
return
}
account.Balance -= money
fmt.Println(“取款成功~~”)
当在取款时,取款是改变最终的余额,如果没有将上文中的函数字段封装起来,直接 account.Balance -= money 是不合理的;若去取钱,明明余额只有1块钱,结果要去取10000块钱,这时需加一段代码,对它进行一个交验,检测数据是否合理,这段代码可体现封装的好处。对别的用户来说,只需输入要取款的金额,再把密码输进去,最后通知取款成功;当输入金额或密码不正确时,便会直接退出。
3. 如何体现封装
(1)对结构体中的属性进行封装
(2)通过方法,实现包装
例如:
//定义一个结构体 Account
type Account struct {
Account string
Pwd string
balance float64
}
将属性小写,本应为 Balance 的改为 balance ,如上文蓝色字体所示,在这里如果想将余额封装起来,需写小写的 b ,于是别的包便不能返回,但是本包是可以返回的,所以说 Golang 不像其他编程一样强调封装,它更强调一种简洁性。若想去操作某属性,就必须通过方法,或者通过包来进行封装,别的包用不了本包的一些方法和属性,这都能体现出封装。
4. 封装的实现步骤
(1)将结构体、字段(属性)的首字母小写(不能导出了,其他包不能使用,类似 private )
(2)给结构体所在包提供一个工厂模式的函数,首字母大写,类似一个构造函数
(3)提供一个首字母大写的 Set 方法(类似其他语言的 public ),用于对属性判断并赋值
func (var 结构体类型名) SetXxx (参数列表)(返回值列表){
//加入数据验证的业务逻辑
var.字段 = 参数
}
(4)提供一个首字母大写的 Get 方法(类似其他语言的 public ),用于获取属性的值
func (var结构体类型名)GetXxx(){
return var.字段;
}
在上述步骤的第三步中:要用大写的 Set 的原因为,若想用别的包来使用它,便只能提供一个 Set 方法,对它的字段进行一个设置,比如上文中的代码,其类似于 public ,因为首字母大写。若要带其他包来操作首字母小写的字段,就需给此结构体绑定一个 Set 方法,此处通过 SetXxx 来设置,在设置时可以加入自己的业务逻辑,例如可将上文中的字段设成 Age ,然后需先设置一个值,且前面可以加业务逻辑进行判断,并且参数列表中的年龄必须在1-150岁之间,方能设置,否则拒绝设置。即这必须通过授权的函数,才能操作私有的 Age 。
5. 特别说明
在 Golang 开发中并没有特别强调封装,因为 Golang 本身就是做了很多简化,这点并不像 Java ,学过 Java 的都知道,一般来说 Java 里面的所有字段都会做成私有属性,每个属性都设置一堆 Get、Set功能,但在 Golang 里并没有特别强调封装,它认为没有必要,Golang 认为在做这些事情时应该由编程去控制,且作为一个程序员应该保证代码是正确的,若设置一个200岁的年龄,是不合理的,这时可以加 if 判断。所以要特别提醒学过 Java 的朋友,不要总是用 Java 的语法特性来看待 Golang ,且学到后面会发现, Golang 连构造函数都没有,所以 Golang 本身是做了很多简化的。