小猴子继承了老猴子,这样老猴子拥有的能力包括字段,方法就会自动的被老猴子继承。小猴子不需要做任何处理就可以拿到老猴子的字段和它的方法,因为是继承关系。
但是小猴子还会其他的技能,比如还会像小鸟一样飞翔,希望像鱼一样可以游泳。这样就可以通过实现的关系,通过实现接口的方式来增强小猴子的能力。
当一个结构体继承了另外一个结构体,那么这个结构体就拥有了继承结构体的字段和方法。如果这个结构体希望去扩展它的一些方法而不去破坏继承关系那么就可以通过实现的方式。
接口是对继承的一种补充。继承之后的新结构体实现了接口并不会去影响老的结构体。(其实也就是通过实现接口来扩展新的结构体的功能,这样并没有影响老的结构体以及其继承关系)
在不去破坏继承关系的基础上,对结构体功能进行扩展。其实就是解藕的方式去扩展结构体的功能。
- package main
- import "fmt"
-
- type Monkey struct {
- Name string
- }
-
- // 给monkey结构体绑定了一个方法叫做climbing
- func (m *Monkey) climbing() {
- fmt.Println(m.Name, "生来会爬树")
- }
-
- type Bird interface {
- Flying()
- }
-
- type Fish interface {
- Swimming()
- }
-
- type LittleMonkey struct {
- Monkey //继承关系
- }
-
- func (l *LittleMonkey) Flying() {
- fmt.Println(l.Name, "会飞")
- }
-
- func (l *LittleMonkey) Swimming() {
- fmt.Println(l.Name, "会游泳")
- }
-
- func main() {
- lm := &LittleMonkey{
- Monkey{
- Name: "悟空",
- },
- }
-
- lm.climbing()
- lm.Flying()
- lm.Swimming()
- }
-
- 悟空 生来会爬树
- 悟空 会飞
- 悟空 会游泳
对上面代码的小结:
1)当 A 结构体继承了B结构体,那么A结构就自动的继承了B结构体的字段和方法,并且可以直接使用
2)当A结构体需要扩展功能,同时不希望去破坏继承关系,则可以去实现某个接口即可,因此我们可以认为:实现接口是对继承机制的补充!
现在要求足球运动员和大学生掌握英语这个技能。
第一种方式就是将学语言这个技能这个方法放到运动员结构体里面去。但是篮球运动员不需要掌握这个英语技能。所以直接将方法写到运动员结构体这个地方是不合理的。
所以这里需要去定义一个接口,让需要实现接口的结构体去实现即可,这样不会影响到其他的结构体,解藕了。
这样不破坏继承关系,同时还可以保障规范性。
实现接口vs继承
>接口和继承解决的问题不同
继承的价值主要在于:解决代码的复用性(可以让结构体去继承另外一个结构体,这样重复的代码就不需要再去写了)和可维护性(被继承的结构体增加一个方法,其他的结构体就拥有了字段和方法)。
接口的价值主要在于:设计,设计好各种规范(方法),让其它自定义类型去实现这些方法。
>接口比继承更加灵活
接口比继承更加灵活,继承是满足is-a的关系,而接口只需满足like-a的关系。
接口在一定程度上实现代码解耦