【Go语言04-2】关于Go语言中的方法详解以及不提供继承机制的解决方案

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................

类型内嵌套了一个类型,外部的类型直接调用嵌套类型内的变量,可以直接调用,也可以按照嵌套连接的方式调用。

上一篇:CSS去除firefox点击链接时的虚线边框


下一篇:Android Studio之could not reserve enough space for object heap