继承与组合模式在定义和使用方式上的主要区别
- 继承模式(Go语言中通过匿名字段模拟):
- 定义方式:在Go语言中没有传统面向对象语言那样的继承关键字,而是通过在结构体中嵌入匿名字段来模拟继承。匿名字段本质上就是没有名字的字段,通常是一个类型名。当一个结构体嵌入另一个结构体(匿名字段)时,就好像是继承了被嵌入结构体的成员。
- 使用方式:嵌入结构体的字段和方法可以像本结构体自己的字段和方法一样直接访问,语法简洁。访问时不需要通过匿名字段的名字,直接使用字段或方法名即可。
- 组合模式:
- 定义方式:组合是将一个结构体作为另一个结构体的普通字段进行定义。被组合的结构体字段有明确的名字。
- 使用方式:访问组合结构体的字段和方法时,需要通过组合结构体的字段名来访问,相对继承模式(匿名字段模拟)的访问方式会稍显冗长。
示例代码
- 继承模式(匿名字段模拟)示例:
package main
import "fmt"
// 基础结构体
type Animal struct {
Name string
}
func (a Animal) Speak() {
fmt.Printf("%s makes a sound\n", a.Name)
}
// 继承自Animal的结构体
type Dog struct {
Animal
Breed string
}
func main() {
myDog := Dog{
Animal: Animal{Name: "Buddy"},
Breed: "Golden Retriever",
}
myDog.Speak() // 直接调用继承自Animal的Speak方法
fmt.Println(myDog.Name) // 直接访问继承自Animal的Name字段
}
- 组合模式示例:
package main
import "fmt"
// 被组合的结构体
type Engine struct {
Power int
}
func (e Engine) Start() {
fmt.Printf("Engine with power %d started\n", e.Power)
}
// 组合结构体
type Car struct {
Name string
Engine Engine
}
func main() {
myCar := Car{
Name: "Toyota",
Engine: Engine{
Power: 150,
},
}
myCar.Engine.Start() // 通过组合的Engine字段访问Start方法
fmt.Println(myCar.Name)
}