博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Golang笔记(二)面向对象的设计
阅读量:6852 次
发布时间:2019-06-26

本文共 2456 字,大约阅读时间需要 8 分钟。

Golang笔记(二)面向对象的设计

Golang本质还是面向过程的语言,但它实现了一些OOP的特性,包括抽象、封装、继承和多态。

抽象和封装

Golang和C语言一样以struct为数据结构核心,不同的是Golang的struct可以定义自己的函数,这使得struct有了一些class的特点,所以Golang具有OOP里抽象和封装的概念。举个栗子来说,f是os.OpenFile()函数返回的File类型指针,File结构体实现了Close()函数,通过f.Close()调用File结构体里的Close()函数。下面是File和其Close()函数的定义:

type File struct {    ...}...func (f *File) Close() error {    ...}

Embedding模拟继承

Golang提供一种称为组合(Composition)的方法实现类似继承的特性。本质上Golang并没有继承(extend)这个概念,Composition是通过在struct里进行嵌套包含的方式提供了类似继承的方法。Composition有两种形式:非匿名组合(has-a)和匿名组合(Pseudo is-a)。

has-a就是简单的struct包含,struct A里包含了struct B,通过A.B.Func()调用了B里的Func(),这种直接调用的方式并不让人觉得是继承。
Pseudo is-a即Golang的Embedding特性,通过在struct A里匿名字段来假装A从B里继承。
看如下栗子,来理解一下Golang的Embedding机制:

type A struct {    ...}func (a *A) Func1() {    fmt.Printf("A Func1 is called")}func (a *A) Func2() {    fmt.Printf("A Func2 is called")}type B struct {    A //Embedded struct A    ...}func (b *B) Func1() {    fmt.Printf("B Func1 is called")}func main() {    B.Func2() //B继承了A的Func2(),此处输出:A Func2 is called    B.Func1() //B重写了Func1(),此处输出:B Func1 is called}

以上栗子说明Golang支持方法重写,但要注意它并不支持方法的重载。如下面代码A.Func2里调用a.Func1并不会被重载成B.Func1:

func (a *A) Func2() {    fmt.Printf("A Func2 is called")    a.Func1()  //此处a还是A,并不会被重载为B}func main() {    B.Func2() //输出:A Func2 is called 和 A Func1 is called}

除了不支持重载,Golang也不支持多继承。如struct C如果继承了struct A和struct B,必须显示引用A和B里的函数以区分其中相同的函数名。同样Embedding机制也不提供多态特性,在上面的栗子中将B类型变量赋值给A类型的变量会报编译错误。Golang并不符合面向对象中的一个重要基本原则--里氏代换原则(Liskov Substitution Principle LSP)。

所以,Golang只是模拟继承特性。

Interface实现多态

Golang通过interface提供了多态的功能。Golang的interface设计最牛逼之处在于,任何数据结构只要实现了interface所定义的函数,就自动实现了这个interface。相比c++或者java要在class里进行冗长的声明,Golang的这个设计大大简化了interface的定义方式。Golang通过"interface"关键字定义了一套接口。如下代码是package "io"里定义的Reader和Writer接口:

type Reader interface {        Read(p []byte) (n int, err error)}type Writer interface {        Write(p []byte) (n int, err error)}

如下是一些常用的package的数据结构里实现的Reader和Writer接口:

  1. os.File.Read()和os.File.Write()
  2. strings.Reader.Read()
  3. bufio.Reader.Read()和bufio.Writer.Write()
  4. bytes.Buffer.Read()和bytes.Buffer.Write()

当然你也可以定义自己的数据结构实现Reader和Writer接口。这样的数据结构变量即可直接用于interface变量的赋值。通过下面这个栗子即可快速理解Interface的作用:

func myRead(r Reader) {    r.Read()}func main() {    f, err := os.Open("./file")    myRead(f) //use os.File as Reader Interface    r := strings.NewReader("this is a string")    myRead(r) //use strings.Reader as Reader Interface}

综上,Golang实现了OOP的一些特性,使其易于面向对象的编程思路。

转载于:https://www.cnblogs.com/jimbo17/p/8485377.html

你可能感兴趣的文章
【Android学习之旅1】研究概述
查看>>
我很幸运
查看>>
Excel数据筛选出来后修改再粘贴进去的方法
查看>>
STM32F4的sct文件理解
查看>>
复制目录结构
查看>>
第 1 章 虚拟化 - 008 - LVM 类型的 Storage Pool
查看>>
PowerPoint 2007 如何把背景音乐嵌入到PPt文件当中
查看>>
手动安装linux操作系统
查看>>
[学习windows/记录篇]站点之间建立***
查看>>
Hbase权限配置以及使用手册
查看>>
vertical-align,text-align 和 align的区别
查看>>
Unity3d多线程
查看>>
炉石传说 C# 开发笔记 (源代码整理公开)
查看>>
前端文摘:Web 开发模式演变历史和趋势
查看>>
最大子数组和问题的解
查看>>
cout设置输出数据不显示科学计数法
查看>>
zoj 1659 Mobile Phone Coverage(矩形面积并)
查看>>
python学习 day3
查看>>
Centos 6.4下用Squid配置反向代理多个内网WEB服务器
查看>>
王者荣耀之父姚晓光“奇葩”的工作理念
查看>>