前言
- 一切都是我自行理解,可能有错,如果之后我意识到了,或者有人愿意提醒我,我会及时更正。
- 有部分知识铺垫,可以跳过。
正文
何为面向对象?
- 我通俗的介绍一下吧。
- 例子1:
面向过程:比如计算 1+1+2+2。你可以定义三个函数,依次计算1+1,2+2,4+4。
面向对象:你可以定义一个对象的方法,这个方法专门用来计算加法的,你用这个对象调用了这个方法,传入1,1,2,2,它会给你计算出来,而且你不仅可以通过这个方法计算1+1+2+2,还可以计算5+6+7+8。
- 例子2:
洗衣服面向过程:你买个洗衣机,打开洗衣机,放入衣服,放入洗衣粉,启动。
洗衣服面向对象:你老婆具有:去买洗衣机、打开洗衣机的能力,你妈妈具有:放入衣服、放入洗衣粉、和启动的能力。你是一个“对象”,你负责“调用”你的老婆和妈妈。
面向对象的三大特性
- 封装 :根据职责将属性和方法封装到一个抽象的类中。
- 继承 :实现代码的重用,相同的代码不需要重复的编写。
- 多态: 不同的子类对象调用相同的父类方法,产生不同的执行结果。
go语言是如何实现面向对象的?
- 第一点,结构体。
1、定义并初始化一个结构体,我们可以认为这个结构体对象就是传统的**“实例对象”**
2、结构体种可以定义字段,我们将其理解为类属性;
3、在go语言中,是有函数和方法的区别的,同名的方法,不同名的结构体接收类型,可以被不同的**“实例对象”**进行调用,而这些方法只能被其规定的结构体接收类型调用,可以理解为“类方法”。( 封装)
4、结构体本身是可以实现继承的。( 继承)
- 第二点,接口。
1、接口中可以定义方法,它不需要去实现,可以将实现接口中定义的所有方法的结构体对象赋给初始化接口的对象,该接口对象可以根据结构体对象的不同,调用相同名字的方法,产生不同的结果。
2、理解上一句可能有点困难,那么我介绍一个情况。定义一个函数,其参数为接口类型。调用该函数时能作为参数传入该函数的结构体对象对应的结构体,一定实现了该接口定义的方法名。在函数内部调用某被实现的一个方法,会因为传入的结构体对象不同,方法名虽然一样,但是产生的结果不一样,进而该函数的执行结果不同。参考代码片1
3、那么如果我们将这个函数,换为一个方法呢?该方法被实现该结构体的子结构体对象调用了,是不是就成了:不同的子类调用相同的父类方法,产生不一样的执行结果?( 多态)参考代码片2
4、理解上面的描述,可能还是有点困难,但是如果你把文字都读完了,云里雾里的时候, 结合下面的代码就很容易理解了。
ps:补充,接口也是可以继承的。
- 第三点:其实关于上述表述,我自己还有有所疑问的,因为结构体本身就可以继承,不同的子结构体对象,调用相同的父结构体对象的方法,也是可以实现多态的。可能接口的意义就在于:它可以实现一个位置参数可以接收不同的数据类型吧。
code1:go多态的体现(函数调用版)
package main
import "fmt"
type Humaner interface {
sayhi()
}
type Student struct {
name string
id int
}
func (temp *Student) sayhi() {
fmt.Printf("Student[%s,%d]sayhi\n", temp.name, temp.id)
}
type Teacher struct {
addr string
group string
}
func (temp *Teacher) sayhi() {
fmt.Printf("Teacher[%s,%s]sayhi\n", temp.addr, temp.group)
}
type Mystr string
func (temp *Mystr) sayhi() {
fmt.Printf("Mystr[%s]sayhi\n", *temp)
}
func WhoSayHi(i Humaner) {
i.sayhi()
}
func main() {
s := &Student{"mike", 666}
t := &Teacher{"bj", "go"}
var str Mystr ="hello mike"
WhoSayHi(s)
WhoSayHi(t)
WhoSayHi(&str)
}
code2:go多态的体现(方法继承版)
package main
import "fmt"
type Humaner interface {
sayhi()
}
type Student struct {
name string
id int
}
func (temp *Student) sayhi() {
fmt.Printf("Student[%s,%d]sayhi\n", temp.name, temp.id)
}
type Teacher struct {
addr string
group string
}
func (temp *Teacher) sayhi() {
fmt.Printf("Teacher[%s,%s]sayhi\n", temp.addr, temp.group)
}
type Mystr string
func (temp *Mystr) sayhi() {
fmt.Printf("Mystr[%s]sayhi\n", *temp)
}
type Principal struct {
}
type PrSon1 struct {
Principal
}
type PrSon2 struct {
Principal
}
func (pr *Principal) WhoSayHi(i Humaner) {
i.sayhi()
}
func main() {
s := &Student{"mike", 666}
t := &Teacher{"bj", "go"}
var str Mystr = "hello mike"
pr := &Principal{}
prS1 := &PrSon1{Principal{}}
prS2 := &PrSon2{Principal{}}
pr.WhoSayHi(s)
prS1.WhoSayHi(t)
prS2.WhoSayHi(&str)
}