Go语言基础08(面向对象(方法))

一、面向对象程序设计思想

\quad Go语言支持面向对象程序设计思想。面向对象(Object Oriented, OO)就是将要研究的事物抽象成对象,然后对对象的状态和行为进行定义。

1.1 对象

\quad Go语言里,对象(Object)可以是最简单的内置数据类型,或者是复杂的结构体。对象不仅能表示具体的事物,还能表示抽象的规则、计划或事件。

1.2 对象的状态

\quad 每一个对象都具有状态,对象通常用数值来描述它的状态。

1.3 对象的操作

\quad 对象还应有操作,用于改变对象的状态,操作就是对象的行为。在Go语言中,对对象的操作称为Method(方法),Method就是在函数前增加了一个接收者(Receiver)对象。这样,操作就和对象真正关联起来了。

1.4 面向对象编程的好处

  • 封装
  • 继承
  • 多态

二、Method 方法

2.1 Method 的基本定义

  • Go语言的Method类似于一个函数,只是函数名前多了个绑定类型参数——receiver
  • Method中的Receiver可以是内置类型、自定义类型、结构体或指针类型。
  • Method的基本定义格式如下:
    func (recv receiver_type)funcName(param1 param1Type, ...)(return1 returnType1, ...){
    	......
    }
    
  • Method的基本定义案例:
    type Rectangle struct { // 矩形对象
    	width  int
    	height int
    }
    
    func (rectangle Rectangle) area() int { // 函数area()是Rectangle对象的一个方法
    	return rectangle.width * rectangle.height // 计算矩形面积
    }
    
    func main() {
    	rect := Rectangle{3, 4}
    	fmt.Println(rect.area()) // 12
    }
    

2.2 多个 Method 可以同名

  1. 在定义Method时,多个Method可以同名,但如果接收者不一样,那Method就不一样。
  2. 如果普通类型作为Receiver,它只是一个值传递;而指针类型作为Receiver,它将是一个引用传递。两者的差别在于,指针作为Receiver会对实例对象的内容发生操作,而普通类型作为Receiver仅是以副本作为操作对象,并不对原实例对象发生操作。
  3. Method的名字可能一样,但如果接收者不一样,那Method就不一样。
  4. Method里面可以访问接收者的字段,使用点号“.”操作符访问。
  • 案例:
    type Rectangle struct { // 矩形对象
    	width  int
    	height int
    }
    
    type Circle struct { // 圆形对象
    	radius float32
    }
    
    func (rectangle Rectangle) area() int { // 函数area()是rectangle对象的一个方法
    	return rectangle.width * rectangle.height // 计算矩形面积
    }
    
    func (circle Circle) area() float32 { // 函数area()是circle对象的一个方法
    	return circle.radius * circle.radius * math.Pi // 计算圆形面积
    }
    
    func main() {
    	rectangle := Rectangle{3, 4}
    	circle := Circle{5}
    	fmt.Println(rectangle.area()) // 12
    	fmt.Println(circle.area()) // 78.53982
    }
    

2.3 指针作为 Receiver

\quad 如果普通类型作为Receiver,它只是一个值传递;而指针类型作为Receiver,它将是一个引用传递。两者的差别在于,指针作为Receiver会对实例对象的内容发生操作,而普通类型作为Receiver仅是以副本作为操作对象,并不对原实例对象发生操作。

\quad 和其他面向对象语言相比,在Go语言中没有隐藏的this指针。而在C++JavaC#这类语言中,它们的成员方法中都带有一个隐藏的this指针,而在Python语言中会隐藏一个self参数,它和其他语言的this作用一样。

  • 案例:定义一个结构体对象coordinate,它用于记录平面坐标值xy,方法swap()的作用是将坐标值xy对换。首先使用普通类型作为Receiver,观察程序运行结果;再使用指针类型作为Receiver,观察程序运行结果。
    type Coordiante struct {
    	x int
    	y int
    }
    
    func (coordiante Coordiante) swap() {
    	coordiante.x, coordiante.y = coordiante.y, coordiante.x
    	// 值传递:普通类型作为Receiver,在方法swap()中对对象属性值的操作并不会改变原实例的值
    	fmt.Println(coordiante.x, coordiante.y) // 8 6
    }
    
    func (coordiante *Coordiante) swap2() {
    	coordiante.x, coordiante.y = coordiante.y, coordiante.x
    	// 引用传递:指针类型作为Receiver,在方法swap()中对对象属性值的操作会直接影响到原实例的值
    	fmt.Println(coordiante.x, coordiante.y) // 8 6
    }
    
    func main() {
    	coordiante := Coordiante{6, 8}
    	coordiante.swap()
    	fmt.Println("值传递:", coordiante.x, coordiante.y) // 值传递: 6 8
    	(&coordiante).swap2()
    	fmt.Println("引用传递:", coordiante.x, coordiante.y) // 引用传递: 8 6
    }
    

2.4 匿名 Receiver

  • 如果方法代码中不适用Receiver参数,那么就可以省略Receiver的变量名,此时的接收者将是一个匿名Receiver。示例如下:
    type Object struct {
    	id   int
    	name string
    }
    
    func (Object) msgbox() {
    	fmt.Println("This is a object!")
    }
    
    func (*Object) msgBox() {
    	fmt.Println("This is a object!")
    }
    
    func main() {
    	obj := Object{}
    	ptr := &obj
    	obj.msgbox()
    	ptr.msgBox()
    }
    

2.5 Method 的继承

\quad 通过前面的学习,我们了解到通过匿名字段可以实现字段继承,在本节中还会发现Go语言的一个神奇之处,即Method也是可以继承的。如果匿名字段实现了一个Method,那么包含这个匿名字段的Struct对象也能调用该Method

  • 案例:结构体People作为结构体TeacherStudent的匿名字段,sayHi()是为People实现的一个方法。作为外层结构,TeacherStudent同时也继承了People所拥有的方法,所以在TeacherStudent的对象中可以直接调用方法sayHi()
    type People struct {
    	name  string
    	phone string
    }
    
    type Teacher struct {
    	People
    	department string
    }
    
    type Student struct {
    	People
    	school string
    }
    
    func (people People) sayHi() {
    	fmt.Printf("Hi, I'm %s, you can call me on %s.\n", people.name, people.phone)
    }
    
    func main() {
    	teacher := Teacher{People{"张三", "010-11001"}, "Computer Science"}
    	teacher.sayHi()
    	student := Student{People{"李四", "010-22002"}, "Tsinghua University"}
    	student.sayHi()
    }
    
    输出:
    Hi, I'm 张三, you can call me on 010-11001.
    Hi, I'm 李四, you can call me on 010-22002.
    

2.6 Method 的重写

\quad 在上例中,如果Student想要实现自己的sayHi()方法,可以采用Method重写的方法来解决。这和匿名字段重名是一样的道理,即外部方法会隐藏匿名字段同名方法。所以可以在Student上再定义一个Method,重写了匿名字段的方法。示例如下:

type People struct {
	name  string
	phone string
}

type Teacher struct {
	People
	department string
}

type Student struct {
	People
	school string
}

func (people People) sayHi() {
	fmt.Printf("Hi, I'm %s, you can call me on %s.\n", people.name, people.phone)
}

func (student Student) sayHi() {
	fmt.Printf("Hi, I'm %s, I study in %s, call me on %s.\n", student.name, student.school, student.phone)
}

func main() {
	teacher := Teacher{People{"张三", "010-11001"}, "Computer Science"}
	teacher.sayHi()
	student := Student{People{"李四", "010-22002"}, "Tsinghua University"}
	student.sayHi()
}

输出:

Hi, I'm 张三, you can call me on 010-11001.
Hi, I'm 李四, I study in Tsinghua University, call me on 010-22002.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软耳朵DONG

觉得文章不错就鼓励一下作者吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值