发布于 

Golang面向对象特性

“Golang是不是支持面向对象”这本身就是一个值得思考的话题,官方文档给出的答案是“Yes and no”

虽说Golang中是有类型的存在,也允许面向对象的编程风格,但是却没有类型层次结构。Golang中没有对类型继承提供支持,而是通过复合来进行 扩展,并通过类型嵌入来简化复合的使用。Go 中的类型嵌入并不是继承机制,类型的嵌入不支持最基本的继承特性:

  • 子类替换
  • 方法重载(override)

Go中的接口机制与其他语言截然不同,实现接口的类型完全不依赖于接口定义。接口作为方法签名的集合,任何类型的方法集中只要拥有与之对应的全部方法,就表示它实现了该接口。

接口

接口使用 interface 关键字声明,任何实现接口定义方法的类都可以实例化该接口,接口和实现类之间没有任何依赖,我们可以实现一个新的类当做 Sayer 来使用,而不需要依赖 Sayer 接口,也可以为已有的类创建一个新的接口,而不需要修改任何已有的代码

1
2
3
4
type Sayer interface {
Say(message string)
SayHi()
}

继承

继承使用组合的方式实现

1
2
3
4
5
6
7
8
9
10
11
type Animal struct {
Name string
}

func (a *Animal) Say(message string) {
fmt.Printf("Animal[%v] say: %v\n", a.Name, message)
}

type Dog struct {
Animal
}

Dog 将继承 Animal 的 Say 方法,以及其成员 Name

覆盖

子类可以重新实现父类的方法

1
2
3
4
// override Animal.Say
func (d *Dog) Say(message string) {
fmt.Printf("Dog[%v] say: %v\n", d.Name, message)
}

Dog.Say 将覆盖 Animal.Say

多态

接口可以用任何实现该接口的指针来实例化

1
2
3
4
var sayer Sayer

sayer = &Dog{Animal{Name: "Panda"}}
sayer.Say("hello world")

但是不支持父类指针指向子类,下面这种写法是不允许的

1
2
var animal *Animal
animal = &Dog{Animal{Name: "Panda"}}

同样子类继承的父类的方法引用的父类的其他方法也没有多态特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
func (a *Animal) Say(message string) {
fmt.Printf("Animal[%v] say: %v\n", a.Name, message)
}

func (a *Animal) SayHi() {
a.Say("Hi")
}

func (d *Dog) Say(message string) {
fmt.Printf("Dog[%v] say: %v\n", d.Name, message)
}

func main() {
var sayer Sayer

sayer = &Dog{Animal{Name: "Panda"}}
sayer.Say("hello world") // Dog[Panda] say: hello world
sayer.SayHi() // Animal[Panda] say: Hi}

上面这段代码中,子类 Dog 没有实现 SayHi 方法,调用的是从父类 Animal.SayHi,而 Animal.SayHi 调用的是 Animal.Say 而不是Dog.Say,这一点和其他面向对象语言有所区别,但是可以用下面的方式来实现类似的功能,以提高代码的复用性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func SayHi(s Sayer) {
s.Say("Hi")
}

type Cat struct {
Animal
}

func (c *Cat) Say(message string) {
fmt.Printf("Cat[%v] say: %v\n", c.Name, message)
}

func (c *Cat) SayHi() {
SayHi(c)
}

func main() {
var sayer Sayer

sayer = &Cat{Animal{Name: "Panda"}}
sayer.Say("hello world") // Cat[Panda] say: hello world
sayer.SayHi() // Cat[Panda] say: Hi}