全栈编程

Balance $ 2,317
Item Sold 1230
文章作者: 全栈编程@luboke.com
版权声明: 本文章为go语言体系课视频教程配套电子书,版权归 全栈编程@luboke.com所有,欢迎免费学习,转载必须注明出处!但禁止任何商业用途,否则将受到法律制裁!

知识大纲 【go语言体系课】面向对象大纲知识大纲,版权@luboke.com,受法律保护。

什么是多态(是什么)

多态同一个行为具有多个不同表现形式。也就是说一个类实例(对象)的相同方法在不同场景下有不同表现形式。多态机制使内部结构不同的对象可以共享相同的外部接口。
这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。最大的优点就是说可以降低类型之间的耦合度,对吧

在go语言当中多态:用接口实现:某个类型的实例可以赋给它所实现的任意接口类型的变量。类型和接口是松耦合的,并且多重继承可以通过实现多个接口实现。

多态,是指一个类实例的相同方法在不同情形有不同表现形式。

多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

多态的作用(为什么要多态)

知识点引入

  • 张三的儿子娶媳妇,通知李五去他家喝喜酒(这里就是一个方法),但是李五有事不能来,李五就让他的三个儿子其中一个代表他老爹李五去喝喜酒(这里就是一个方法),使用的是他们老爹的喝喜酒方法,就像他老爹本人一样。

  • 不必编写每一子类的功能调用,可以直接把不同子类当父类看,屏蔽子类间的差异,提高代码的通用率/复用率

  • 父类引用可以调用不同子类的功能,提高了代码的扩充性和可维护性

多态的使用(怎么使用)

1.定义接口与类型,让类型去实现接口中的方法

1.定义接口时,方法不能实现
2.一个类型如果实现了接口中的所有方法,我们就说这种类型实现接口,不仅仅结构体,也可以是内置类型
3.自定义类型可以实现多个接口

定义格式

type 接口名 interface {
    方法名1(参数列表)(返回值)
    方法名2(参数列表)(返回值)
    方法名3(参数列表)(返回值)
    。。。
}
通过自定义类型来实现接口中的所有方法
//定义类型
type T struct {
}
type TT string

//方法接收者
func (this *T)方法名1()(返回值){}
func (this *T)方法名2()(返回值){}
func (this *T)方法名3()(返回值){} 

main.go中定义一个结构体一个接口pay,增加两个方法topay()info()

type pay interface {
    topay()
    info()
}

同时我们来定义一个结构体payment

type payment struct {
    paymentmethod string
}

让这个结构体去实现接口pay中的所有方法

func (this *payment)topay()  {
    fmt.Println("topay:",this.paymentmethod)
}

func (this *payment)info()  {
    fmt.Println("info:",this.paymentmethod)
}

我们来定义payment类型的变量_payment

_payment := &payment{paymentmethod:"alipay"}

这要我们就可以通过这个变量去调用接口中的方法了,因为我们的结构体payment实现了接口中所有的方法

_payment.info()
_payment.topay()

注意点
一个变量实现了接口当中所有方法,接口就可以指向这个变量
接口内的方法不能实现,体现了程序的多态与低偶合高内聚

var _pay pay
//一个变量实现了接口当中所有方法,接口就可以指向这个变量
_pay = _payment
_pay.info()
_pay.topay()

我们一般不这样使用,后面我们会讲解他的使用场景

2.自定义类型也可以实现接口

main.go文件中,定义两个接口

type write interface {
    echo()
    out()
}

type read interface {
    scan()
    input()
}

我们来基于内置类型创建自定义类型

//自定义类型,基于内置类型
type readwrite string

让自定义类型来实现上面定义的两个接口中的所有该当

//自定义类型`readwrite`实现`write`接口中的`echo()`方法
func (this *readwrite)echo()  {
    fmt.Println("readwrite:echo()")
}

//自定义类型`readwrite`实现`write`接口中的`out()`方法
func (this *readwrite)out()  {
    fmt.Println("readwrite:out()")
}

//自定义类型`readwrite`实现`read`接口中的`scan()`方法
func (this *readwrite)scan()  {
    fmt.Println("readwrite:scan()")
}

//自定义类型`readwrite`实现`read`接口中的`input()`方法
func (this *readwrite)input()  {
    fmt.Println("readwrite:input()")
}

这样我们自定义的类型readwrite就实现了两个接口中的所有方法,在main.go文件中调用

var _readwrite readwrite
_readwrite.echo()

多重继承接口,所有的方法都要实现

//多重继承格式
type InterfaceAA interface {
    InterfaceA
    InterfaceB
}

作业
自由发挥实现一个类多重继承的功能

综合案例

为了巩固面向对象知识点,通过结合面向对象三大特征,综合的对面向对象的知识进行进阶

企业项目中经常涉及到与日志存储的业务,比如针对web项目的日志存储

比如磁盘IO操作的日志:磁盘进行数据拷贝读取一般会有读写日志,记录读取到的位置,即当前数据在磁盘的哪个碰头哪个扇区上

比如网络请求的日志:去访问某个网站一般会有请求日志的记录,用于分析来访客户,刻画出用户的区域,访问兴趣爱好(网购时的一个典型例子,用户浏览记录写cookie)

这里我们模拟一个网络读写日志与磁盘读写日志的例子
定义写操作接口write

type write interface {
    echo()
    out()
}

定义公共日志结构体Log,做为父类,并为其增加方法writeLog(),传递一个write接口类型的变量

//日志结构体
type Log struct {
    name string
    content string
    addtime int64
}

func (this *Log)writeLog(_write write)  {
    fmt.Println(this.name+"---"+this.content)
    _write.echo()
    _write.out()
}

定义网络读写结构体与磁盘读写结构体,继承自父类Log

type NetLog struct {
    Log
}

type IOLog struct {
    Log
}

定义自定义类型,iowritenetwrite,分别实现write接口中的所有方法

type iowrite string
func (this *iowrite)echo()  {
    fmt.Println("iowrite:echo()")
}
func (this *iowrite)out()  {
    fmt.Println("iowrite:out()")
}

type netwrite string
func (this *netwrite)echo()  {
    fmt.Println("netwrite:echo()")
}
func (this *netwrite)out()  {
    fmt.Println("netwrite:out()")
}

main.go文件中

//父类引用指向子类对象
//一个变量实现了接口当中所有方法,接口就可以指向这个变量
log := &Log{
    name:    "微信小程序支付日志",
    content: "微信小程序支付日志内容",
    addtime: 0,
}

var _iowrite *iowrite
var _netwrite *netwrite 
//writeLog的参数是一个write类型,我们这里的iowrite实现了write接口中的所有方法,所以可以传递iowrite
//相当于write (指向)-> iowrite
log.writeLog(_iowrite)

//writeLog的参数是一个write类型,我们这里的netwrite实现了write接口中的所有方法,所以可以传递netwrite
//相当于write (指向)-> netwrite
log.writeLog(_netwrite)

调用者多态的一面


netlog := &NetLog{Log{
    name:    "微信小程序网络支付日志",
    content: "微信小程序网络支付日志内容",
    addtime: 0,
}}
//writeLog的调用者是Log,我们的NetLog继承自Log,所以可直接调用
netlog.writeLog(_netwrite)

filelog := &IOLog{Log{
    name:    "微信小程序文件支付日志",
    content: "微信小程序文件支付日志内容",
    addtime: 0,
}}
//writeLog的调用者是Log,我们的IOLog继承自Log,所以可直接调用
filelog.writeLog(_iowrite)
  • 知识点引入

  • 应用场景

  • 面试事项

  • 工作经验

知识大纲 【go语言体系课】面向对象大纲知识大纲,版权@luboke.com,受法律保护。

go语言规范中英文对照: effective go

文章作者: 全栈编程@luboke.com
版权声明: 本文章为go语言体系课视频教程配套电子书,版权归 全栈编程@luboke.com所有,欢迎免费学习,转载必须注明出处!但禁止任何商业用途,否则将受到法律制裁!
copyright © 2020 全栈编程@luboke.com