如果你是一个有着其它面向对象语言开发经验的开发者,那么肯定知道什么是继承与子类了,简单来说,他就是一种类型继承另一种类型的方法、行为与属性,继承者具有被继承者全部的方法与属性,比如一个公司的“职员”它继承人大类“人”,职员具有人的所有属性与行为,一辆法拉利具有一辆人所具有的所有属性等等例子数不胜数,但是虽然阿斯顿·马丁也具有一辆车的所有属性与行为,却与法拉利是不一样的。

我们定义一辆车的行为,那么法拉利与阿斯顿·马丁都会具有这种行为,比如“车都是具有发动机的”或者“车都有方向盘或者其它能控制方向的东西”,但是如果我们定义了法拉利的行为和属性则并不一定会导致车或者阿斯顿·马丁也具有同样的行为与属性,比如1947年5月25日,法拉利自己设计并制造的运动车获罗马最高奖,但是这并不代表阿斯顿·马丁也有着同样的这个历史属性。

从上面这些示例中可以看到,子类继承父类的一些行为与属性,子类的行为与属性不一定会同时在父类上也体现,也并不一定会体现在继承自同一父类的其它子类上,我们将上面关于法拉利或者阿斯顿·马丁与汽车的例子体现到程序上面来,那将是这样的一种情况:我们定义一个Struct,其名为Car*,它具有一个方法 *numberOfWheels() 可以获取到车的轮胎数量,我们再定义一个StructFerrari 继承自 Car ,那么我们就可以使用 Ferrari.numberOfWheels() 方法来获取到 Ferrari 的轮胎数量。

我以前的文章Go Struct中的匿名字段 与 Go Structs 中的方法 介绍过,通过匿名字段可以实现上面的要求:

package main
import "fmt"
type Car struct {
    wheelCount int
}
// 定义 Car 的行为
func (car Car) numberOfWheels() int {
    return car.wheelCount
}
type Ferrari struct {
    Car // 匿名字段 Car
}
func main() {
    f := Ferrari{Car{4}}
    fmt.Printf("一辆法拉利有 %d 个轮胎n", f.numberOfWheels())
}

输出为:

一辆法拉利有 4 个轮胎

在上面的示例中,我们仅仅只定义了 Car 的行为或者方法,但是当我们将Car作为一个匿名字段作为Ferrari的属性是,Ferrari就自动的具有了Car的所有方法。那么我们如果再创建一个新的 Struct :AstonMartin 其结果是怎么样的呢?

package main
import "fmt"
type Car struct {
    wheelCount int
}
// 定义 Car 的行为
func (car Car) numberOfWheels() int {
    return car.wheelCount
}
type Ferrari struct {
    Car // 匿名字段 Car
}
// 定义只有 Ferrari 专属的方法
func (f Ferrari) sayHiToSchumacher() {
    fmt.Println("Hi Schumacher!")
}
type AstonMartin struct {
    Car
}
//添加只有 AstonMartin 专属的方法
func (a AstonMartin) sayHiToBond() {
    fmt.Println("Hi Bond, James Bond!")
}
func main() {
    f := Ferrari{Car{4}}
    fmt.Printf("一辆法拉利有 %d 个轮胎n", f.numberOfWheels())
    f.sayHiToSchumacher()
    a := AstonMartin{Car{4}}
    fmt.Printf("一辆阿斯顿马丁有 %d 个轮胎n", a.numberOfWheels())
    a.sayHiToBond()
}

输出为:

一辆法拉利有 4 个轮胎
Hi Schumacher!
一辆阿斯顿马丁有 4 个轮胎
Hi Bond, James Bond!

在上面示例中,AstonMartin 与 Ferrari 同时具有 numberOfWheels() 方法,并且又都具有它们自己的方法,但是像下面这样的就不行:

func main() {
    f := Ferrari{Car{4}}
    fmt.Printf("一辆法拉利有 %d 个轮胎n", f.numberOfWheels())
    f.sayHiToBond()
    a := AstonMartin{Car{4}}
    fmt.Printf("一辆阿斯顿马丁有 %d 个轮胎n", a.numberOfWheels())
    a.sayHiToSchumacher()
}

输出为:

./inherit3.go:27: f.sayHiToBond undefined (type Ferrari has no field or method sayHiToBond)
./inherit3.go:30: a.sayHiToSchumacher undefined (type AstonMartin has no field or method sayHiToSchumacher)

标签: none

评论已关闭