package main
import "fmt"
// Animal 基础类型
type Animal interface {
Speak() string
}
// Dog 基于Animal扩展的类型
type Dog struct {
Name string
}
// Speak 重写Animal的Speak方法
func (d Dog) Speak() string {
return fmt.Sprintf("Woof! My name is %s", d.Name)
}
// Cat 基于Animal扩展的类型
type Cat struct {
Name string
}
// Speak 重写Animal的Speak方法
func (c Cat) Speak() string {
return fmt.Sprintf("Meow! My name is %s", c.Name)
}
// MakeSound 接受Animal接口参数并调用Speak方法
func MakeSound(a Animal) {
fmt.Println(a.Speak())
}
实现思路
- 定义接口:首先定义
Animal
接口,包含 Speak
方法。这是模拟继承关系中的“基类方法”,任何实现了 Speak
方法的类型都被认为实现了 Animal
接口。
- 定义扩展类型:分别定义
Dog
和 Cat
结构体类型,它们不直接继承自 Animal
,但通过实现 Speak
方法,隐式地实现了 Animal
接口。这样就模拟了从 Animal
扩展出 Dog
和 Cat
的关系。
- 多态实现:
MakeSound
函数接受 Animal
接口类型的参数。当传入 Dog
或 Cat
类型的实例时,会根据实例的实际类型调用对应的 Speak
方法,从而实现多态效果。
可能存在的问题
- 代码重复:如果
Animal
有更多方法,Dog
和 Cat
可能需要重复实现部分逻辑。虽然Go语言没有传统继承,但可以通过组合和接口嵌套等方式来减少重复代码。
- 缺乏继承层次结构:Go语言没有像传统面向对象语言那样明确的继承层次,这可能使代码结构在大型项目中较难理解和维护,特别是对于习惯传统继承的开发者。
- 接口兼容性:如果修改了
Animal
接口(比如添加新方法),所有实现了该接口的类型(如 Dog
和 Cat
)都必须实现新方法,否则编译会报错。