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 协议》,转载必须注明作者和本文链接
没有 get 到重写方法的含义. 我理解的 SpecialFruit 就是一个独立的 struct, 它的 cost 方法, 就是它的方法, 只是重名了而已, 如果不给它定义 cost 方法, 就没法调用吧
@rachel Fruit 是嵌入的。specialFruit.Fruit.Cost() 还是可以调用的
@JaguarJack 哦, 懂了, 因为 specialFruit 结构中有一个字段类型是 Fruit, 确实有点继承的意思, 谢谢啦 :star2:
@rachel 你可以用继承来理解