## **面向对象编程三大特性\-封装**
#### **封装介绍**
封装(encapsulation)就是把抽象出的字段和对字段的操作封装在一起,数据被保护在内部,程序的其它包只有通过被授权的操作(方法),才能对字段进行操作
封装的理解和好处
1)隐藏实现细节
2)提可以对数据进行验证,保证安全合理(Age)
#### **封装的实现步骤**
1)将结构体、字段(属性)的首字母小写(不能导出了,其它包不能使用,类似private)
2)给结构体所在包提供一个工厂模式的函数,首字母大写。类似一个构造函数
3)提供一个首字母大写的Set方法(类似其它语言的public),用于对属性判断并赋值
```
func(var结构体类型名)SetXxx(参数列表)(返回值列表){
//加入数据验证的业务逻辑
var.字段=参数
}
```
4)提供一个首字母大写的Get方法(类似其它语言的public),用于获取属性的值
```
func(var结构体类型名)GetXxx(){
return var.age;
}
```
特别说明:在Golang开发中并没有特别强调封装,这点并不像Java.所以提醒学过java的朋友,
不用总是用java的语法特性来看待Golang,Golang本身对面向对象的特性做了简化的.
#### **快速入门案例**
请大家看一个程序(person.go),不能随便查看人的年龄,工资等隐私,并对输入的年龄进行合理的验证。设计:model包(person.go)main包(main.go调用Person结构体)
model/person.go
![](https://img.kancloud.cn/b8/be/b8be14e1b5b9142c276ab43ecac51ca3_1065x653.png)
![](https://img.kancloud.cn/70/7a/707a6d97633ecd0dc1fab63447724c09_1007x579.png)
main/main.go
![](https://img.kancloud.cn/a1/a7/a1a75f3c03ba66a15bcbcb12e4c7f967_1007x478.png)
## **面向对象编程三大特性-继承**
1)字段和方法几乎相同了相同但是我们却写了相同的代码,代码复用性不强
2)出现代码冗余,而且代码不利于维护,同时也不利于功能的扩展。
3)解决方法-通过继承方式来解决
![](https://img.kancloud.cn/16/8e/168e6674b80460e63505df844c07b21f_706x383.png)
也就是说:在Golang中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性。
**嵌套匿名结构体的基本语法**
```
typeGoodsstruct{
Namestring
Priceint
}
typeBookstruct{
Goods//这里就是嵌套匿名结构体Goods
Writerstring
}
```
**继承给编程带来的便利**
1)代码的复用性提高了
2)代码的扩展性和维护性提高了
**继承的深入讨论**
1)结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段、方法,都可以使用。【举例说明】
![](https://img.kancloud.cn/28/7c/287c37b192af85412dd5f95b8f1491ee_787x671.png)
2)匿名结构体字段访问可以简化,如图
![](https://img.kancloud.cn/06/9d/069d47e33b6818258c1563f36a70a975_788x453.png)
对上面的代码小结
(1)当我们直接通过b访问字段或方法时,其执行流程如下比如b.Name
(2)编译器会先看b对应的类型有没有Name,如果有,则直接调用B类型的Name字段
(3)如果没有就去看B中嵌入的匿名结构体A有没有声明Name字段,如果有就调用,如果没有继续查找..如果都找不到就报错.
3)当结构体和匿名结构体有相同的字段或者方法时,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分【举例说明】
![](https://img.kancloud.cn/0f/d5/0fd5f947a18a191ce7de64ac4a181303_557x270.png)
4)结构体嵌入两个(或多个)匿名结构体,如两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确指定匿名结构体名字,否则编译报错。【举例说明】
![](https://img.kancloud.cn/c2/2e/c22e06d9218c256798bf3120bfd9e6ff_837x500.png)
5)如果一个struct嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体的字段或方法时,必须带上结构体的名字
![](https://img.kancloud.cn/ac/77/ac77445006541e4278cc856e5c3cda16_652x224.png)
6)嵌套匿名结构体后,也可以在创建结构体变量(实例)时,直接指定各个匿名结构体字段的值
![](https://img.kancloud.cn/9a/da/9ada469e2a67282980c0c65b4ab56f09_459x745.png)
**结构体的匿名字段是基本数据类型,如何访问,下面代码输出什么**
![](https://img.kancloud.cn/5b/f7/5bf7aa9d1b27c1ae253379a2e7263adf_534x591.png)
说明
1)如果一个结构体有int类型的匿名字段,就不能第二个。
2)如果需要有多个int的字段,则必须给int字段指定名字
### **多重继承说明**
如一个struct嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承。
![](https://img.kancloud.cn/3b/fa/3bfa2002c7ea8dd520427d903d18356c_617x383.png)
**多重继承细节说明**
1)如嵌入的匿名结构体有相同的字段名或者方法名,则在访问时,需要通过匿名结构体类型名来区分。【案例演示】
![](https://img.kancloud.cn/99/c1/99c1b9f1da881d031bf5cd740e13ff62_743x107.png)
2)为了保证代码的简洁性,建议大家尽量不使用多重继承