Golang初级系列教程-继承和子类
对面向对象熟悉的人对继承和子类并不陌生。简单来说,就是一种类型继承另一个类型行为的能力。员工有人基本的行为,还有其独特的行为。法拉第包括汽车的所有特性,同时具有更多性能。阿斯顿·马丁,也具有汽车的所有特性,同时也有不同于法拉第或者其它汽车自身的特点。所以,如果我们实现一个 Car
并且定义其属性方法,那么法拉第和阿斯顿·马丁都可以进行重用,而不是重新开始设计。简而言之,就是继承一个更加泛化的类型或者说类。在面向对象语言中,有与之对应的类和子类一说,子类继承父类的所有属性方法,并且子类可以继续定义其符合自身特色的属性方法。
这种模式在编程时应如何运用呢?设想,有一个类 Car
,有一个方法叫做 numberOfWheels()
。接着创建 Car
的子类 Ferrari
,在程序中的含义就是我们可以直接使用 Ferrari.numberOfWheels()
——即子类获得父类所有的属性和方法。
通过我们之前所学的 结构体中的匿名字段 和 结构体函数,可以利用 Go
实现同样的设计。如果同我一样,有面向对象编程的背景,几个例子可以形象的说明这一点。
package main
import "fmt"
type Car struct {
wheelCount int
}
// define a behavior for Car
func (car Car) numberOfWheels() int {
return car.wheelCount
}
type Ferrari struct {
Car //anonymous field Car
}
func main() {
f := Ferrari{Car{4}}
fmt.Println("A Ferrari has this many wheels: ", f.numberOfWheels()) //no method defined for Ferrari, but we have the same behavior as Car.
}
A Ferrari has this many wheels: 4
上面的代码中,定义了 Car
方法。之后,将 Car
作为 Ferrari
的匿名字段,至此 Ferrari
能够访问所有关于 Car
的属性和方法。虽然在这里,我们不是通过继承父类而是通过组合实现的,但是产生的效果是相同的——获取了父类的所有属性和方法。是不是很神奇,让我们进一步设计 AstonMartin
,并添加更多的自有特性。
package main
import "fmt"
type Car struct {
wheelCount int
}
func (car Car) numberOfWheels() int {
return car.wheelCount
}
type Ferrari struct {
Car
}
// a behavior only available for the Ferrari
func (f Ferrari) sayHiToSchumacher() {
fmt.Println("Hi Schumacher!")
}
type AstonMartin struct {
Car
}
// a behavior only available for the AstonMartin
func (a AstonMartin) sayHiToBond() {
fmt.Println("Hi Bond, James Bond!")
}
func main() {
f := Ferrari{Car{4}}
fmt.Println("A Ferrari has this many wheels: ", f.numberOfWheels()) //has car behavior
f.sayHiToSchumacher() //has Ferrari behavior
a := AstonMartin{Car{4}}
fmt.Println("An Aston Martin has this many wheels: ", a.numberOfWheels()) //has car behavior
a.sayHiToBond() //has AstonMartin behavior
}
A Ferrari has this many wheels: 4
Hi Schumacher!
An Aston Martin has this many wheels: 4
Hi Bond, James Bond!
上面的代码中 , Ferrari
和 AstonMartin
都可以直接访问 Car
的 numberOfWheels
,二者都可以认为是一种 Car
。另外,Ferrari
定义了之后自身才能访问的 sayHiToSchumacher
, AstonMartin
定义了只能自己访问的 sayHiToBond
。
简而言之,通过 Go
中匿名字段的概念,实现了同继承和子类相同的概念。
译者注:Go
本身并不是面向对象语言,继承和子类只是一种编程模式,话又说回来,什么又是面向对象呢?
Golang一种神奇的语言,让我们一起进步