Go语言没有继承,但是却有方法,方法是Go语言面向对象的主要特征。
Go语言的方法是关联到类型的,且其存在与类没有任何关系,仅仅和类型有关系。
Go语言的方法定义非常像函数,仅仅是在函数名称前面定义了方法接受者或者叫接收器。
type Retangle struct{
w,h float64
}
func (r Rectangle) area() float64{
return r.w * r.h
}
一、方法定义与调用
Go语言的方法定义非常像函数,仅仅是在函数名称前面定义了方法接受者或者叫接收器。本例定义了r,它是上面定义的Rectangle类型的接收器,其主要作用就是代表该方法的调用者。
接收器类似于其他语言的self、this等 关键字,Go语言里面没有这些关键字。Go语言中的接收器是编程者自己定义的,名称越短越好,一般都是对应类型的首字母。
注意:
Go语言的方法也可以称为类型方法、接收器将类型和方法绑定在一起。
package main
import "fmt"
//定义一个矩形类型
type Rectangle struct{
w,h float64
}
func main() {
rec := Rectangle{w:2,h:3}
fmt.Println(area(rec.w,rec.h))
fmt.Println(rec.area())
}
//定义一个矩形求面积的函数 ===================>>> 函数
func area(w,h float64) float64{
return w*h
}
//定义一个矩形类型的方法 ===================>>> 方法
func (r Rectangle) area() float64 {
return r.w * r.h
}
方法的概念是从函数演变而来的,并且Go语言
里面没有方法重载概念。
用户可以给任何自定义的类型定义方法,定义一个或多个都可以,不过自定义类型和对应的方法在同一个包中。
给Go语言
内置的类型(比如int
)定义方法是不可以的,因为要求类型定义和
其对应的方法必须在同一个包内。
二、指针类型调用方法
在调用方法的时候,对应的调用对象和接收器进行数据传递采用的也是值传递方式。
如果主调对象的数据量比较大,可以把接收器定义为指针类型,通过指针类型还可以在方法内直接修改调用对象的值。
//定义一个矩形
type Rectangle struct{w,h float64}
func main() {
p := &Rectangle{w:2,h:3}
fmt.Println("&p :",p) // &p : &{2 3}
fmt.Println(p.area())
rec := Rectangle{w:2,h:3}
rp := &rec
fmt.Println("&rp :",rp) // &rp : &{2 3}
fmt.Println(rp.area())
fmt.Println((&rec).area())
fmt.Println(rec.area()) //会隐式的加上*rec,合法用法
//Rectangle{w:2,h:3}.area() //会报错,因为这种方式Go无法获取变量的地址
Rectangle{w:2,h:3}.area2() //合法用法,因为area2方法的接收器不是指针类型,采用值传递
}
//定义一个接收器为指针类型的方法
func (r *Rectangle) area() float64 {
return r.w * r.h
}
//定义一个接收器为矩形类型的方法
func (r Rectangle) area2() float64 {
return r.w*r.h
}
area()
的方法的调用者是指针类型,所以代码中注释改行调用该方法会报错。area2()
的方法的调用者是类型,所以不需要使用指针类型调用。
注意:隐式指针
适用于方法的调用者是指针类型,当我们使用类型直接调用,则会隐式的加上
p := &Rectangle{w:2,h:3}
rec := Rectangle{w:2,h:3}
fmt.Println(rec.area()) //会隐式的加上*rec,合法用法
fmt.Println((*p).area()) //会隐式的加上*rec,合法用法
【注意】
如果自定义的类型本身已经是指针类型,例如type p *int
,则不允许为该类型定义方法。
对于func (p) f() {...}
, 采用p类型的这种方法定义编译是通不过的。
三、Go语言中不提供继承机制
package main
import (
"fmt"
"image/color"
)
//定义一个矩形
type Rectangle struct{w,h float64}
//定义一个彩色矩形
type ColorRect struct {
Rectangle
Color color.RGBA
}
func main() {
var cr ColorRect
cr.h = 3
cr.w = 2
fmt.Println(cr.area())
cr.printNum()
cr.Rectangle.printNum()
}
//定义一个接收器为矩形类型的方法
func (r Rectangle) area() float64 {
return r.w * r.h
}
//定义一个函数
func (r Rectangle) printNum(){
fmt.Println("num................")
}
运行结果:
6
num................
num................
类型内嵌套了一个类型,外部的类型直接调用嵌套类型内的变量,可以直接调用,也可以按照嵌套连接的方式调用。