Go语言面向对象编程(二)方法

1.方法

       在面向对象编程中,一个对象其实也就是一个简单的值或者一个变量,在这个对象中会包含一些函数,这种带有接收者的函数,我们称为方法(method)。本质上,一个方法则是一个和特殊类型关联的函数。

       一个面向对象的程序会用方法来表达其属性和对应的操作,这样使用这个对象的用户就不需要直接去操作对象,而是借助方法来做这些事情。

      在Go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法。

      方法总是绑定对象实例,并隐式将实例作为第一实参(receiver),方法的语法如下:

func  (receiver   ReceiverType)  funcName(parameters)  (results)

  • 参数receiver可以任意命名。如方法中未曾使用,可省略参数名。
  • 参数receiver类型就是T或*T。基类型T不能是接口或指针。
  • 不支持重载方法,也就是说,不能定义名字相同但是不同参数的方法。

2.面向对象编程与面向过程编程对比

package main

import (
	"fmt"
)

//实现两个数相加
//面向过程
func Add01(a, b int) int {
	return a + b
}

//面向对象,方法:给某个类型绑定一个函数
type long int

//tmp叫接收者,接收者就是传递的一个参数
func (tmp long) Add02(other long) long {
	return tmp + other
}

func main() {
	result := Add01(1, 2) //普通函数调用方式
	fmt.Println("result = ", result)

	//定义一个变量
	var a long = 2
	//调用方法格式:变量名.函数(所需参数)
	r := a.Add02(3)
	fmt.Println("result = ", r)

	//面向对象只是换了一种表现形式
}

输出:

3.为结构体类型添加方法

package main

import (
	"fmt"
)

type Person struct {
	name string
	sex  byte
	age  int
}

//带有接收者的函数叫方法
func (tmp Person) PrintInfo() {
	fmt.Println("tmp = ", tmp)
}

//通过一个函数,给成员赋值
func (p *Person) SetInfo(n string, s byte, a int) {
	p.name = n
	p.sex = s
	p.age = a
}

func main() {
	//定义同时初始化
	p := Person{"mike", 'm', 18}
	p.PrintInfo()

	//定义一个结构体类型
	var p2 Person                  //p2为面型对象中的对象
	(&p2).SetInfo("yoyo", 'n', 22) //SetInfo为成员函数
	p2.PrintInfo()
}

输出:

4.值语义和引用语义

package main

import (
	"fmt"
)

type Person struct {
	name string
	sex  byte
	age  int
}

//修改成员变量的值
//接收者为普通变量,非指针,值语义,一份拷贝
func (p Person) SetInfoValue(name string, sex byte, age int) {
	p.name = name
	p.sex = sex
	p.age = age
	fmt.Printf("SetInfoValue &p = %p\n", &p)
}

//接收者为指针变量,引用传递
func (p *Person) SetInfoPointer(name string, sex byte, age int) {
	p.name = name
	p.sex = sex
	p.age = age
	fmt.Printf("SetInfoPointer &p = %p\n", p)
}

func main() {
	var s1 Person = Person{"go", 'm', 22}
	fmt.Printf("&s1 = %p\n", &s1)

	//值语义,
	s1.SetInfoValue("mike", 'm', 18)
	fmt.Println("s1 = ", s1) //打印内容

	//引用语义
	var s2 Person = Person{"go", 'm', 22}
	fmt.Printf("&s2 = %p\n", &s2)
	(&s2).SetInfoPointer("yoyo", 'm', 18)
	fmt.Println("s2 = ", s2)
}

输出:

5.方法集

【1】指针变量的方法集

package main

import (
	"fmt"
)

type Person struct {
	name string
	sex  byte
	age  int
}

func (p Person) SetInfoValue() {
	fmt.Println("SetInfoValue")
}

func (p *Person) SetInfoPointer() {
	fmt.Println("SetInfoPointer")
}

func main() {
	//假如,结构体变量是一个指针变量,他能够调用那些方法,这些方法是一个集合,简称方法集
	p := &Person{"mike", 'm', 18}
	p.SetInfoPointer()    //func (p *Person) SetInfoPointer()
	(*p).SetInfoPointer() //把(*p)转化为p然后调用

	//内部做的转换,先把指针,转成*p后再调用
	p.SetInfoValue()
}

输出:

【2】指针变量的方法集

package main

import (
	"fmt"
)

type Person struct {
	name string
	sex  byte
	age  int
}

func (p Person) SetInfoValue() {
	fmt.Println("SetInfoValue")
}

func (p *Person) SetInfoPointer() {
	fmt.Println("SetInfoPointer")
}

func main() {
	p := Person{"mike", 'm', 18}
	//内部,先把p转为&p再调用
	p.SetInfoPointer() //func (p *Person) SetInfoPointer()
}

输出:

6.方法的继承

package main

import (
	"fmt"
)

type Person struct {
	name string
	sex  byte
	age  int
}

//有个学生继承Person字段,成员和方法都继承了
type Student struct {
	Person
	id   int
	addr string
}

func (tmp *Person) PrintInfo() {
	fmt.Printf("name=%s,sex=%c,age=%d", tmp.name, tmp.sex, tmp.age)
}

func main() {
	s := Student{Person{"mike", 'm', 18}, 1, "bj"}
	s.PrintInfo()  //s可以使用Person的方法
}

输出:

7.方法的重写

package main

import (
	"fmt"
)

type Person struct {
	name string
	sex  byte
	age  int
}

//有个学生继承Person字段,成员和方法都继承了
type Student struct {
	Person
	id   int
	addr string
}

//Student也实现了一个方法,这个方法和Person的方法同名,叫重写
func (tmp *Student) PrintInfo() {
	fmt.Printf("Student name=%s,sex=%c,age=%d\n", tmp.name, tmp.sex, tmp.age)
}

func (tmp *Person) PrintInfo() {
	fmt.Printf("Person name=%s,sex=%c,age=%d\n", tmp.name, tmp.sex, tmp.age)
}

func main() {
	s := Student{Person{"mike", 'm', 18}, 1, "bj"}
	//就近原则,先找本作用域的方法,找不到再用继承的方法
	s.PrintInfo()

	//显示调用继承的方法
	s.Person.PrintInfo()
}

输出:

8.方法值

package main

import (
	"fmt"
)

type Person struct {
	name string
	sex  byte
	age  int
}

func (p Person) SetInfoValue() {
	fmt.Printf("SetInfoValue: %p, %v\n", &p, p)
}

func (p *Person) SetInfoPointer() {
	fmt.Printf("SetInfoPointer: %p, %v\n", p, p)
}

func main() {
	p := Person{"mike", 'm', 18}
	fmt.Printf("main: %p, %v\n", &p, p)

	p.SetInfoPointer() //传统调用方式

	//保存方法入口地址
	pFunc := p.SetInfoPointer //这个就是方法值,无需再传递接收者。
	pFunc()                   //等价于p.SetInfoPointer()

	vFunc := p.SetInfoValue
	vFunc() //等价于p.SetInfoValue()
}

输出:

9.方法表达式

package main

import (
	"fmt"
)

type Person struct {
	name string
	sex  byte
	age  int
}

func (p Person) SetInfoValue() {
	fmt.Printf("SetInfoValue: %p, %v\n", &p, p)
}

func (p *Person) SetInfoPointer() {
	fmt.Printf("SetInfoPointer: %p, %v\n", p, p)
}

func main() {
	p := Person{"mike", 'm', 18}
	fmt.Printf("main: %p, %v\n", &p, p)

	//方法值pFunc := p.SetInfoPointer 隐藏了接收者
	//方法表达式
	f := (*Person).SetInfoPointer
	f(&p) //显式把接收者传递过去 ----》p.SetInfoPointer(&p)

	f2 := (Person).SetInfoValue
	f2(p) //显式把接收者传递过去 ----》p.SetInfoValue(p)
}

输出:

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值