这个问题不是像“继承与组合”这样的问题。
我完全理解继承与组合的不同之处,我知道Liskov 替换原则,钻石问题,它们的优缺点,这两个概念似乎都很简单。但是到处都有很多关于继承和组合的问题,我想,也许我误解了这个简单的想法。
让我们专注于Go。Go 是一种来自 Google 的语言,每个人都很兴奋,它没有继承,没有类,但它有组合,这很酷。对我来说,Go 中的组合为您提供与其他语言(C++、Java、...)中的继承完全相同的功能 - 组件方法会自动公开并作为后续结构的方法使用,如下所示:
package main
import (
"fmt"
)
type Car struct{
name string
}
func (c *Car) move() bool {
return true
}
type MyCar struct{
Car
}
func main() {
var c MyCar
fmt.Print(c.move())
}
综上所述,组合优于继承,因为:
- 更灵活(允许您在运行时更改组件,因此您可以影响“类”的工作方式。
- 没有钻石问题(但钻石问题是可以解决的,所以这不是很强的优势)
如果你考虑 Go 和它的接口(每个对象,具有由接口定义的方法,都隐含地实现了这个接口)你有最终的解决方案吗?我们可以说带有一些语法糖的组合可以代替继承吗?
这样的设计符合 Liskov 替换原则。我是否错过了某些东西或继承(从任何语言中知道)与 Go 中已知的组合(和接口)相比没有优势?
===== 编辑1 =====
为了澄清起见,可以Go
使用“标准”组合机制,如下所示(此示例的行为与前一个类似):
package main
import (
"fmt"
)
type Car struct{
name string
}
func (c *Car) move() bool {
return true
}
type MyCar struct{
car Car
}
func (c *MyCar) move() bool {
return c.car.move()
}
func main() {
var c MyCar
fmt.Print(c.move())
}
但是,如果您像前面的示例一样使用它,则所有方法都隐含在“MyCar 类”中。