go语言基础-----07-----方法

1 方法的介绍

  • 1)方法的概念:简单说就是一个对象里面的函数,称为方法。
  • 2)在go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法。
  • 3)方法总是绑定对象实例,并隐式将实例作为第一参数。
  • 4)方法的语法:
func (receiver receiverType) funcName(parameters) (results)
// 1. receiver 为任意名字。
// 2. receiverType为调用者的类型。可以是T或者*T。注意T本身不能是接口或者指针。
例如T=int,但是不能是*int。想要指针可以这样做:T=int后,单独加一个*// 代码解释:
// 1. 正确写法
type myint int
func (s *myint) Add() (r int)

// 2. 错误写法。因为T类型本身不能是指针。
type myintp *int
func (s myintp) Add() (r int)
  • 5)方法不支持重载,即不支持同样类型中,函数名相同形参不同的方法。注意,不同的类型中,是可以有同样的函数名的。下面例子将会解释到。

2 面向过程和面向对象的函数区别

非常简单,就是将函数封装到了一个对象里面,然后通过变量名 + 点的形式进行调用。利用下面的例子。

package main

import "fmt"

// go本身没有long类型
type long int

func Add01(a, b long)long{
	return a + b
}

func (t long)Add02(b long)long{
	return t + b
}

func main(){
	// 1. 面向过程
 	fmt.Println("Add01 = ", Add01(1, 2))

 	// 2. 面向对象
 	var s1 long = 1
	fmt.Println("Add02 = ", s1.Add02(5))

}

3 结构体类型添加方法

package main

import "fmt"

type Persion struct {
	name string
	sex byte
	age int
}

// 带有接受者的函数叫方法
func (t Persion) PrintInfo(){
	fmt.Println("PrintInfo = ", t)
}

func (t *Persion) SetInfo(n string, s byte, a int){
	t.name = n
	t.sex = s
	t.age = a
}

func main(){

	// 1. 普通变量作为隐含实例传参
	p := Persion{"hc", 'w', 24}
	p.PrintInfo()

	// 2. 指针变量作为隐含实例传参
	(&p).SetInfo("lqq", 'w', 24)
	p.PrintInfo()
}

4 方法相关注意点

  • 1)接收者本身不能是指针类型,上面在将第1点时也强调过。
// 1. 正确的写法
type long int
func (t long)test(){
}

// 2. 错误的写法
// err:Invalid receiver type 'pointer' ('pointer' is a pointer type)
type pointer *int
func (t pointer)test(){
}
  • 2)go的方法不支持重载。例如下面这样写语法是会报错的。因为接收者的类型一样,并且名字也一样。
type long int
func (t long)test(){

}
type long int
func (t long)test(a int){

}

而下面这样写不会报错,因为接收者类型不一样。可以用C++定义了两个类,类中有同样的成员函数名去理解。

type long int
func (t long)test(){

}

type char byte
func (c char) test(a int){

}

5 接收者的值语义和引用语义

  • 1)普通变量作为接收者是值传递。
  • 2)指针变量作为接收者是引用传递。
    代码看回上面第3点的 结构体类型添加方法。

6 指针类型和变量类型的方法集

方法集实际上是使用指针可以如何调用方法,以及普通变量如何调用方法而已。变量在调用自己的方法集时,不受变量自己是指针还是普通变量的约束,都可以使用 “变量名 + 点(.) + 方法名” 的形式调用。
例如:

package main

import "fmt"

type Persion struct {
	name string
	sex byte
	age int
}

// 带有接受者的函数叫方法
func (t Persion) SetInfoValue(){
	fmt.Println("SetInfoValue")
}

func (t *Persion) SetInfoPointer(){
	fmt.Println("SetInfoPointer")
}

func main(){

	// 1. 结构体变量是一个指针时,它能调用哪些方法,就是一个方法集
	// 指针调用方法的方式
	p := &Persion{"hc", 'w', 24}
	p.SetInfoPointer()
	p.SetInfoValue()	// 它内部会自动转换,将指针p转成 (*p).SetInfoValue(),所以下面的调用方式也是可以的,所以调用方法时不需要考虑是指针还是变量
	(*p).SetInfoValue()

	fmt.Println("===========")

	// 2. 普通变量调用方法的方式
	p2 := Persion{"lqq", 'w', 24}
	p2.SetInfoValue()
	p2.SetInfoPointer()	// 内部转成(&p2).SetInfoPointer(),所以下面的调用方式也是可以的
	(&p2).SetInfoPointer()
}

在这里插入图片描述

7 方法的继承

package main

import "fmt"

type Persion struct {
	name string
	sex byte
	age int
}

// Persion实现了一个方法
func (t *Persion) PrintInfo(){
	fmt.Printf("name=%s, byte=%c, age=%d\n", t.name, t.sex, t.age)
}

// 另一个结构体继承了该Persion,它会继承了所有成员及其方法
type Student struct {
	Persion // 匿名字段
	id int
	addr string
}

func main(){

	s := Student{Persion{"hc", 'w', 24}, 1, "sz"}
	s.PrintInfo()
}

8 方法的重写

go中方法的重写,实际上就是C++的多态(通过虚基类指针、virtual关键字实现)。
下面的go实现多态的例子。

package main

import "fmt"

type Persion struct {
	name string
	sex byte
	age int
}

// Persion实现了一个方法
func (t *Persion) PrintInfo(){
	fmt.Printf("name=%s, byte=%c, age=%d\n", t.name, t.sex, t.age)
}

// 另一个结构体继承了该Persion,它会继承了所有成员及其方法
type Student struct {
	Persion // 匿名字段
	id int
	addr string
}

// Student也添加一个同名的方法PrintInfo
// 注意,因为接收者类型一个是 *Persion、一个是 *Student,它们是不一样的,所以函数名可以同样。
// 这样也叫方法的重写,即实现了多态。
func (t *Student) PrintInfo(){
	fmt.Println("stu = ", t)
}


func main(){

	s := Student{Persion{"hc", 'w', 24}, 1, "sz"}

	// 根据就近原则,调用的是Student.PrintInfo()
	s.PrintInfo()

	// 显示调用才能调用到Persion的PrintInfo()
	s.Persion.PrintInfo()
}

在这里插入图片描述

9 方法值与方法表达式

  • 1)方法值:隐式调用,通过隐式保存接收者来进行调用。
  • 2)方法表达式:显示调用,不会隐式保存接收者,调用时需要显示传实例给对应的接收者类型。

代码例子:

package main

import "fmt"

type Persion struct {
	name string
	sex byte
	age int
}

// 带有接受者的函数叫方法
func (t Persion) SetInfoValue(){
	fmt.Println("SetInfoValue")
}

func (t *Persion) SetInfoPointer(){
	fmt.Println("SetInfoPointer")
}

func main(){

	// 1. 方法值调用
	p := &Persion{"hc", 'w', 24}
	pFunc := p.SetInfoPointer				// 会隐式保存接收者
	pFunc()

	vFunc := p.SetInfoValue
	vFunc()

	fmt.Println("==============")

	// 2. 方法表达式调用
	p2 := Persion{"lqq", 'w', 24}
	f := (*Persion).SetInfoPointer			// 不会隐式保存接收者,所以调用时需要传对应的实例给接收者。(*Persion)表示传实例时是一个地址而不是普通变量。
	f(&p2)									// 需要传实例给接收者类型。

	f2 := (Persion).SetInfoValue			// Persion表示传实例时是一个普通变量而不是地址。
	f2(p2)									// 需要传实例给接收者类型。
}

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值