go 面向对象编程

面向对象#

go 语言面向对象与 C++,Java 等语言不同之处, 在与 go 不支持继承。Go 语言只支持聚合和嵌入, 通过一个简单的例子来了解一下 go 中的聚合和嵌入

type ColoredPoint struct {
            color.Color // 匿名字段(嵌入)
            x, y int    // 具名字段 (聚合)
} 

在 ColoredPoint 结构体中, color.Color 引入其他包的类型,x, y 都属于整型,他们都属于结构体的字段。由于 color.Color 字段是匿名的(因为他没有变量名), 所以称之为匿名字段,即嵌入字段。而 x, y 是有具名的聚合字段。其字段可以通过 point.Color, point.x, point.y 直接访问, 注意的是,如果是匿名字段的话, 可以直接使用其名字最后一部分。
Go 没有继承的概念,所以就没有所谓的虚函数。但是 go 支持类型安全的鸭子类型,而且嵌入也可以实现类似继承的功能。这个都是后话了。

自定义类型#

创建语法

type typeName typeSpecification

typeName 可以使 Go 语言中任意合法的标识符, 而 typeSpecification 可以是任何内置的类型(int string float struct chan)可以是接口, 还可以是方法签名。
看一下例子

type newInt int
type stringMap map[string]string
type people struct{}

var i newInt => var i int   //似乎和C语言的type没啥区别

添加方法#

方法是作用在自定义类型的值上的一类特殊函数, 通常自定义类型的值会被传递给函数。该值可以以指针或者只的形式传递,这取决于方法如何定义。定义方法的语法几乎等同于定义函数, 出了需要在 func 关键字和方法名之间必须写上接受者 (写于括号中) 之外。
我们可以为任何自定义的类型添加一个或者多个方法。一个方法的接受者总是该类型的值, 或者该类型值的指针。
对于任何一个给定的类型, 每个方法名都是必须唯一的。
举个列子

type People struct {
    age int
    name string
}
func (this *People) printAge() {
    fmt.Println(this.age)
}

func(this *People) printName() {
    fmt.Println(this.name)
}

func main() {
    jack := People{name:"jack", age:12}
    jack.printAge()
    jack.printName()
}

输出

12
jack

首先定义 People 结构体类型, 然后给两个方法作为接受者, 这时候便是给 Peopel 添加个两个方法。

重写方法#

来举个例子来说明

type Fruit struct {
        price int
        quantity int
}

func (fruit *Fruit) Cost() int {
    return fruit.price * fruit.quantity
}

type SpecialFruit struct {
        Fruit  // 匿名字段 (嵌入)
        markup int  // 具名字段 (聚合)
}

// 重写
func (specialFruit *SpecialFruit) Cost() int {
    return specialFruit.Fruit.Cost()  * specialFruit.markup
}

func main() {
    res := SpecialFruit{Fruit{price:12, quantity:12}, 10}
    fmt.Println(res.Cost())
}

1440

如果你没有重写的话, 可以试试看, 输出结果就是 144。 直接调用的 嵌入的 Fruit 的 Cost 方法

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 4

没有 get 到重写方法的含义。我理解的 SpecialFruit 就是一个独立的 struct, 它的 cost 方法,就是它的方法,只是重名了而已,如果不给它定义 cost 方法,就没法调用吧

6年前 评论
JaguarJack

@rachel Fruit 是嵌入的。specialFruit.Fruit.Cost () 还是可以调用的

6年前 评论

@JaguarJack 哦,懂了,因为 specialFruit 结构中有一个字段类型是 Fruit, 确实有点继承的意思,谢谢啦 :star2:

6年前 评论
JaguarJack

@rachel 你可以用继承来理解

6年前 评论

开发 @ 家里蹲开发公司
文章
75
粉丝
73
喜欢
359
收藏
260
排名:19
访问:27.4 万
私信
所有博文
社区赞助商