Golang中类面向对象特性
一、类型方法的实例成员复制与类型方法的实例成员引用
在Go中可以类似Java等面向对象语言一定为某个对象定义方法,但是Go中并没有类的存在,可以不严格的将Go中的struct类型理解为面向对象中的类;
type demoObject struct {
id int
}
类的概念有了,那怎么为这个类(struct结构)定义方法呢;Go语言中有两种方式:
1、在类型指针上定义方法;
func (o *demoObject) one() {
fmt.Printf("one方法字段的内存地址:%x\n",
unsafe.Pointer(&o.id))
}
2、在类型上定义方法;
func (o demoObject) two() {
fmt.Printf("one方法字段的内存地址:%x\n",
unsafe.Pointer(&o.id))
}
这两种方式其实定义方式都差不多,区别只是在于方法时定义在类型上还是定义在类型指针上面,就是因为这点区别导致了方法中类型实例有了本质的区别;
在类型上定义方法其类型实例的成员值会进行复制,也就是说每个该类型实例的方法中类型的成员地址也都不一样;
而在类型指针上定义方法其类型实例的成员只是指针复制,所有类型指针上方法的类型成员地址完全一样;
var obj = new(demoObject)
fmt.Printf("main函数obj对象字段的内存地址:%x\n",
unsafe.Pointer(&obj.id))
obj.one()
obj.two()
one方法:o实例的成员id内存地址与obj实例的成员id地址一样
two方法:o实例的成员id内存地址与obj实例的成员id地址不一样
总结来说:
one方法中修改demoObject类型的成员id的值obj实例成员id值也会变化
two方法中修改demoObject类型的成员id的值obj实例成员id值不会变化
二、接口与实现
在Go中实现某接口不需要显式的依赖该接口,只需要在某类型或类型指针上定义与该接口的方法签名完全一致的接口即可;
type inter interface {
hello()
}
func (o *demoObject) hello() {
}
var i inter = new(demoObject)
i.hello()
如上代码所示,即可说类型demoObject实现了inter接口,Go的接口具有非入侵性,由于该特性因此Go语言也具有了dock typing ,也就是鸭子类型;
三、内嵌类型(类似继承并非等同于Java中的继承)
Go中存在这一种匿名内嵌类型,通过匿名内嵌类型可以得到类似与继承的结果;
type base struct {
Id int
}
type level struct {
*base
}
var l=new(level)
fmt.Println(l.Id)
如上代码所示,通过在类型level中引入匿名内嵌类型base,可以使用level类型的实例l调用得到类型base中的成员Id,如果base类型有绑定方法level类型实例一样可以调用该方法。
请注意上面说的是通过内嵌类型可以得到的是类似继承,并非等同于继承,level实例虽然可以访问得到base类型实例,但并不能在level中重写base的方法。两者并非继承与被继承的关系;
四、Go中的多态
Go有接口的存在,是否也存在多态的概念呢。 答案是存在的如下代码所示,与Java中的多态并没有很大区别;
type one struct{}
type two struct{}
type inter interface {
hello()
}
func (o *one) hello() {
fmt.Println("one hello")
}
func (t *two) hello() {
fmt.Println("two hello")
}
func say(i inter) {
i.hello()
}
var o = new(one)
var t = new(two)
say(o)
say(t)
Golang中存在面向对象的某些特征,但又与传统的面向对象语言有着不小区别;如Go中只有类似继承功能,又不等同于其他语言的继承,无法重写方法,也不存在子类于父类的概念;Go中存在接口但空接口代表着是任意类型于Java中的Object类类似但又不一样;