内容简介:学习golang的过程中,有一个比较关注的价值观,golang提倡组合,不提倡继承。看过一些书和资料,感觉对这个概念的解释都不是很满意,特总结这篇文章,大家指正。先说说组合与继承的概念。对设计模式有过了解的同学对这两个名词应该都有初步的理解,我们来总结一下:官方解释就不说了,组合一般理解为 has-a 的关系,继承是is-a的关系。以java为例,组合可以理解为类里边添加的属性(一般是接口类型),继承是extends。
学习golang的过程中,有一个比较关注的价值观,golang提倡组合,不提倡继承。看过一些书和资料,感觉对这个概念的解释都不是很满意,特总结这篇文章,大家指正。
组合与继承
先说说组合与继承的概念。对 设计模式 有过了解的同学对这两个名词应该都有初步的理解,我们来总结一下:
官方解释就不说了,组合一般理解为 has-a 的关系,继承是is-a的关系。以 java 为例,组合可以理解为类里边添加的属性(一般是接口类型),继承是extends。
这里我引用一篇文章的段落 浅谈组合与继承
继承的优缺点 优点: 1,类继承简单粗爆,直观,关系在编译时静态定义。 2,被复用的实现易于修改,sub可以覆盖super的实现。 缺点: 1,无法在运行时变更从super继承来的实现(也不一定是缺点) 2,sub的部分实现通常定义在super中。 3,sub直接面对super的实现细节,因此破坏了封装。 4,super实现的任何变更都会强制子类也进行变更,因为它们的实现联系在了一起。 5,如果在新的问题场景下继承来的实现已过时或不适用,所以必须重写super或继承来的实现。 由于在类继承中,实现的依存关系,对子类进行复用可能会有问题。有一个解决办法是,只从协议或抽象基类继承(子类型化),国为它们只对很少的实现,而协议则没有实现。 组合的优缺点 对象组合让我们同时使用多个对象,而每个对象都假定其他对象的接口正常运行。因此,为了在系统中正常运行,它们的接口都需要经过精心的设计。下面我就来说说他的优缺点 优点: 1,不会破坏封装,因为只通过接口来访问对象; 2,减少实现的依存关系,因为实面是通过接口来定义的; 3,可以在运行时将任意对象替换为其他同类型的对象; 4,可以保持类的封装以专注于单一任务; 5,类和他的层次结构能保持简洁,不至于过度膨胀而无法管理; 缺点: 1,涉及对象多; 2,系统的行为将依赖于不同对象间的关系,而不是定义于单个类中; 3,现成的组件总是不太够用,从而导致我们要不停的定义新对象。
总结来看,我认为,组合相对于继承的优点在于
- 可以利用面向接口编程原则的一系列优点,封装性好,耦合性低
- 相对于继承的编译期确定实现,组合的运行态指定实现,更加灵活
代码演示
网上很少有例子解释清楚golang所提倡的组合的优势,一般就是将一个struct嵌入到另外一个struct里。
package main import ( "fmt" ) type A struct { } func (*A) Hello(name string) { fmt.Println("hello " + name + ", i am a") } type B struct { *A } func main() { name := "Lee" a := A{} a.Hello(name) //hello Lee, i am a b := B{&A{}} b.Hello(name) //hello Lee, i am a }
如上文所述,我认为组合需要与接口结合使用才能体现其精髓。
让我们来看一段改造后的代码:
package main import ( "fmt" ) type IHello interface { Hello(name string) } type A struct { } func (*A) Hello(name string) { fmt.Println("hello " + name + ", i am a") } type D struct { } func (*D) Hello(name string) { fmt.Println("hello " + name + ", i am d") } type B struct { *A } type C struct { IHello } func main() { name := "Lee" a := A{} a.Hello(name) //hello Lee, i am a b := B{&A{}} b.Hello(name) //hello Lee, i am a c := C{&A{}} c.Hello(name) //hello Lee, i am a c = C{&D{}} c.Hello(name) //hello Lee, i am d }
发现不同了吗?
A的指针继承了接口IHello, B中嵌入了具体实现类A,C中嵌入了接口IHello,
B C两者在赋值时,均可嵌入A的指针实例,但是C可以根据运行时上下文指定具体实现,更加灵活。
所以让我们面向接口编程,提倡共用组合与接口的优雅代码
以上所述就是小编给大家介绍的《如何理解go语言提倡组合,不提倡继承》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 028.Python面向对象继承(单继承,多继承,super,菱形继承)
- PHP类继承、接口继承关系概述
- 面向对象:理解 Python 类的单继承与多继承
- java入门第二季--继承--java中的继承初始化顺序
- 前端基本功(七):javascript中的继承(原型、原型链、继承的实现方式)
- 组合还是继承,这是一个问题?——由模式谈面向对象的原则之多用组合、少用继承
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。