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的一些特性,使其易于面向对象的编程思路。

Golang笔记(二)面向对象的设计的更多相关文章

  1. Java基础学习笔记(二) - 面向对象基础

    面向对象 一.面向对象概述 面向对象思想就是在计算机程序设计过程中,参照现实事物,将事物的属性特征.行为特征抽象出来,描述成计算机时间的设计思想.面向对象思想区别于面向过程思想,强调的是通过调用对象的 ...

  2. Java学习笔记(二) 面向对象---构造函数

    面向对象---构造函数 特点 函数名与类名相同 不用定义返回值类型 不写return语句 作用 对象一建立,就对象进行初始化. 具体使用情况 class Student { Student(){ Sy ...

  3. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  4. UML和模式应用学习笔记-1(面向对象分析和设计)

    UML和模式应用学习笔记-1(面向对象分析和设计) 而只是对情节的记录:此处的用例场景为:游戏者请求掷骰子.系统展示结果:如果骰子的总点数是7,则游戏者赢得游戏,否则为输 (2)定义领域模型:在领域模 ...

  5. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

  6. jQuery源码笔记(二):定义了一些变量和函数 jQuery = function(){}

    笔记(二)也分为三部分: 一. 介绍: 注释说明:v2.0.3版本.Sizzle选择器.MIT软件许可注释中的#的信息索引.查询地址(英文版)匿名函数自执行:window参数及undefined参数意 ...

  7. 8.python笔记之面向对象基础

    title: 8.Python笔记之面向对象基础 date: 2016-02-21 15:10:35 tags: Python categories: Python --- 面向对象思维导图 (来自1 ...

  8. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  9. 2018-2019-2 20175306实验二面向对象程序设计《Java开发环境的熟悉》实验报告

    2018-2019-2 20175306实验二面向对象程序设计<Java开发环境的熟悉>实验报告 面向对象程序设计-1 实验要求: 参考:> http://www.cnblogs.c ...

随机推荐

  1. DotNetty 版 mqtt 开源客户端 (MqttFx)

    一.DotNetty背景介绍 某天发现 dotnet  是个好东西,就找了个项目来练练手.于是有了本文的 Mqtt 客户端   (github:  MqttFx ) DotNetty是微软的Azure ...

  2. SqlServer学习笔记【暂】

    Sql学习笔记,暂时先保存在着,等不忙了再整理成章节,如果其中有问题的,还请各位大神不吝赐教! --------------------------------------所有的数据基于Northwi ...

  3. UIPageViewController

    前言 iPhone 和 iPad 都是通过页控件来展示多个桌面,很多 App 在第一次使用时也会使用页控件来介绍自己的功能,页控件的交互效果非常好,适用于把几个简单的页面充分展示出来. 1.UIPag ...

  4. 软件测试就业必备知识点&自学软件测试-Dotest-2019

    软件测试就业必备知识点&自学测试&教学大纲-Dotest-2019

  5. 基于vue框架项目开发过程中遇到的问题总结(一)

    (一)关于computed修改data里变量的值 问题:computed里是不能直接修改data里变量的值,否则在git commit 时会报错 解决:在computed里使用get和set来进行获取 ...

  6. 【bzoj3172】: [Tjoi2013]单词 字符串-AC自动机

    [bzoj3172]: [Tjoi2013]单词 先用所有单词构造一个AC自动机 题目要求的是每个单词在这个AC自动机里匹配到的次数 每次insert一个单词的时候把路径上的cnt++ 那么点p-&g ...

  7. 【以太坊开发】区块链中的预言机:Oraclize原理介绍

    智能合约的作用很多,但是很多数据还是要基于互联网,那么如何在合约中获取互联网中的数据?Oraclize就是为了这个目的而诞生的. 工作原理: 智能合约通过对Oraclize发布一个合约之间的调用请求来 ...

  8. [51nod1239] 欧拉函数之和(杜教筛)

    题面 传送门 题解 话说--就一个杜教筛--刚才那道拿过来改几行就行了-- //minamoto #include<bits/stdc++.h> #define R register #d ...

  9. const常量,常量折叠,字面常量

    const int a=10: 涉及到一个叫常量折叠的概念(认为我这说得太简单或者不好理解的可以google一下它获取更多信息), 即编译器虽然会给a分配空间(如果取a的地址进行操作的时候,会强迫编译 ...

  10. C++基础学习7:new/delete操作符

    在C语言中,动态分配和释放内存的函数是malloc.calloc和free,而在C++语言中,new.new[].delete和delete[]操作符通常会被用来动态地分配内存和释放内存. 需要注意的 ...