package main
import "fmt"
// 定义基础结构体Animal
type Animal struct {
Name string
Age int
}
// 定义Dog结构体,嵌套Animal
type Dog struct {
Animal
}
// 定义Cat结构体,嵌套Animal
type Cat struct {
Animal
}
// 定义Sound接口
type Sound interface {
MakeSound() string
}
// Dog实现Sound接口的MakeSound方法
func (d Dog) MakeSound() string {
return "Woof"
}
// Cat实现Sound接口的MakeSound方法
func (c Cat) MakeSound() string {
return "Meow"
}
// 接收Sound接口类型参数的函数
func makeSound(s Sound) {
fmt.Println(s.MakeSound())
}
func main() {
// 创建Dog实例
dog := Dog{Animal: Animal{Name: "Buddy", Age: 3}}
// 创建Cat实例
cat := Cat{Animal: Animal{Name: "Whiskers", Age: 2}}
// 调用函数展示多态性
makeSound(dog)
makeSound(cat)
}
Go语言与传统面向对象语言多态实现方式的不同之处
- 类型与接口关系:
- Go语言:Go语言中类型与接口的关系是隐式的,只要一个类型实现了接口的所有方法,就隐式地实现了该接口,无需显式声明。例如上面代码中
Dog
和Cat
结构体无需声明自己实现了Sound
接口,只要实现了MakeSound
方法就自动实现了该接口。
- 传统面向对象语言(如Java、C++):在Java中,类必须显式声明实现某个接口(
implements
关键字);在C++中,通过虚函数和继承机制,子类需要显式继承父类接口并实现纯虚函数。
- 继承方式:
- Go语言:Go语言没有传统的类继承机制,通过结构体嵌套来实现代码复用。如
Dog
和Cat
结构体嵌套了Animal
结构体,获得了Animal
的字段。
- 传统面向对象语言:通常使用类继承(如Java的
extends
关键字,C++的:
继承方式),子类继承父类的属性和方法,这种继承是强耦合的,可能导致复杂的继承层次结构。
- 接口实现位置:
- Go语言:接口的实现可以在任何包中,只要类型实现了接口方法即可。这使得代码更加灵活,不同包中的类型可以轻松实现同一接口。
- 传统面向对象语言:接口实现通常在定义类型的同一个地方,与类型定义紧密绑定。