从OOP的角度看Golang
资料来源
Golang中的概念
Golang中引入了在Golang中独有的struct 和 interface,其意义和传统语言中的不同。
概念清单
| Golang | Classic OOP |
|---|---|
| struct | class with fields, only non-virtual methods |
| interface | class without fields, only virtual methods |
| embedding | multiple inheritance AND composition |
| receiver | implicit this parameter |
struct 是一个class但是没有virtual方法
struct 是一个class但是没有virtual方法,比如说:
type Rectangle struct {
Name string
Width, Height float64
}
func(r Rectangle) Area() float64 {
return r.Width + r.Height
}
那么伪代码如下:
class Rectangle
field Name: string
field Width: float64
field Height: float64
method Area() //non-virtual
return this.Width * this.Height
构造器
- 对于每一个基本类型,默认使用0来填充,如果你没有显示的指定其初始值,那么就是0
- 没有指定的类的构造器,只是对每一个类的实例,都有一个通用的构造器。使用类似于JSON格式的字面值常量来构造
function construct ( class, literal)
helper function assignFields ( object, literal) //recursive
if type-of object is "object"
if literal has field-names
for each field in object.fields
if literal has-field field.name
assignFields(field.value, literal.fields[field.name].value) //recurse
else
//literal without names, assign by position
for n=0 to object.fields.length
assignFields(object.fields[n].value, literal.fields[n].value) //recurse
else
//atom type
set object.value = literal.value
// generic constructor main body
var classInstance = new class
assignFields(classInstance, literal)
return classInstance
对于Golang的构造器使用
package main
import . "fmt"
type Rectangle struct {
Name string
Width, Height float64
}
func main() {
var a Rectangle
var b = Rectangle{"I'm b.", 10, 20}
var c = Rectangle{Height: 12, Width: 14}
Println(a)
Println(b)
Println(c)
}
Golang中的嵌入类似于OOP中的没有virtual 方法的多继承
将一个结构体嵌入到另一个结构体,就好像是对非虚成员的多继承。让我们看看一个例子:
type base struct {
a string
b int
}
type derived {
base //嵌入
d int
a float32 //隐藏base中的a字段
}
func main() {
var x derived;
fmt.Printf("%T", x.a) // x.a float32
fmt.Printf("%T", x.base.a) //=> x.
}
当base结构体嵌入到derived结构体中,那么base结构体中的字段和方法都可以在derived结构体中都可用。但是base内部的字段可以被derived中的字段shadowed。在内部,有一个名称叫base 类型为base的字段被创建,。如果将base嵌入到了derived,那么在derived类型可以直接访问base的字段。
Shadowing表示在derived中定义另一个与base 字段和方法相同名字的字段和方法,那么就会存在shadowinig这种情况。一但base中的字段被derived中的shadow,那么可以通过使用base名称来访问隐藏的字段。所有base中的字段,都可以通过隐藏字段的名称base来访问。需要注意的事情:
It is important to note that all inherited methods are called on the hidden-field-struct. It means that a base method cannot see or know about derived methods or fields. Everything is non-virtual.
当和结构体和嵌入这种概念打交道的时候,我们应该知道所有的东西都是在编译期间静态绑定的,所以的引用解析都是在静态编译期间。
When working with structs and embedding, everything is STATICALLY LINKED. All references are resolved at compile time.
多层嵌入
type NamedObj struct {
Name string
}
type Shape struct {
NameObj
color string
isRegular bool
}
type Point struct {
x, y float64
}
type Rectangle struct {
NameObj
Shape
center Point
Width float64
Height float64
}
func main() {
var aRect = Rectange {
NameObj{"name1"},
Shape{NameObj{"name2"}, 0, true},
Point{0, 0},
20,
2.5
}
fmt.Println(aRect.Name)
fmt.Println(aRect.Shape)
fmt.Println(aRect.Shape.Name)
}
等效的伪代码:
class NamedObj
field Name: string
class Shape
inherits NamedObj
field color: int32
field isRegular: bool
class Rectangle
inherits NamedObj
inherits Shape
field center: Point
field Width: float64
field Height: float64
在var aRect Rectangle中,
- aRect.Name and aRect.NamedObj.Name 指的是同意对象
- aRect.color and aRect.Shape.color 指的是同一个东西
- aRect.name and aRect.NamedObj.name 指的是同一个字段, 但是 aRect.NamedObj.name 和 aRect.Shape.NamedObj.name 是不同的字段
- aRect.NamedObj and aRect.Shape.NamedObj 是相同的类型,但是对象不同
方法隐藏
由于所有的golang-struct都是non-virtual的,所以你不可以覆盖这些方法。(当然接口是可以的)比如在NameObj中定义了一个名字叫做show的方法,但是呢,你在struct Rectangle中也定义了其他的方法,那么
Rectangle/show()将会隐藏NameObj/show方法。正如基类的字段一样,你也可以通过使用基类的名称来访问基类被隐藏的方法。
type base struct {
a string
b int
}
func (this base) xyz(){
fmt.Println("xyz, a is ", this.a);
}
// method display
func (this base) display() {
fmt.Println("base, a is:", this.a)
}
type derived struct {
base // embedding
d int
a float32 //-SHADOWED
}
// method display
func(this derived) display() {
fmt.Println("derived a is ", this.a)
}
func main() {
var a derived = derived{base{"base-a", 10}, 20, 2.5}
a.display() // 2.5
a.base.diplay() // base, a is : base-a
a.xyz(); // call base.xyz(), xyz, a is : base-a
}
Golang 方法和接受者
Golang的 struct-method,和类的non-virtual方法类似,但是在如下地方不同:
- struct-method在struct外面定义
- 既然起在struct body外面定义,那么在方法中有了一个名字叫做接受者
- 对于这个接受者的名字,自己可以取一个简单的,一般是struct类型的第一个单词
type NameObj struct {
Name string
}
func(n NameObj) show(){
fmt.Println(n.Name)
}
struct 和 interface
Golang中的interface是一个没有字段的,只有虚方法。interface的设计是为了补充struct。在Golang中
**Structs: ** classes, with fields, ALL NON-VIRTUAL methods **Interfaces: ** classes, with NO fields, ALL VIRTUAL methods
通过严格限定struct是没有virtual的方法,interface是包含所有virtual的方法,通过嵌入来将两者结合起来,从而实现多态。
Interface
Golang interface 是一个没有字段的类,但是包含所有是virtual的函数。考虑到这种定义,那么你能够用interface干的事情:
- 声明一个变量的类型为 type interface
- 实现该interface,在一个struct中实现所有该interface定义的方法
- 嵌入到另一个interface
空接口
在Golang中空接口是没有任何字段和没有任何方法,所以任何struct和基本类型都实现了interface{},这意味着var x interface{}可以容纳任何类型的值。那么我们可以使用interface{}来干什么事情呢?本来什么事情都不可以干,但是我们可以使用type switch,type assertion或反射
使用struct embedding
当你使用struct embedding,那么你就是要创建一个multi-root 体系,通过多继承。你要记住的是,所有的结构体方法都是non-virtual的。这就是为什么struct永远要比使用接口嵌入要快。因为没有接口涉及的时候,所有的函数的调用都是在编译期间就决定了。
从OOP的角度看Golang的更多相关文章
- 从JDK源码角度看Object
Java的Object是所有其他类的父类,从继承的层次来看它就是最顶层根,所以它也是唯一一个没有父类的类.它包含了对象常用的一些方法,比如getClass.hashCode.equals.clone. ...
- Android IOS WebRTC 音视频开发总结(四八)-- 从商业和技术的角度看视频行业的机会
本文主要从不同角度介绍视频行业的机会,文章来自博客园RTC.Blacker,支持原创,转载必须说明出处,欢迎关注个人微信公众号blacker ----------------------------- ...
- 【阿里云产品公测】以开发者角度看ACE服务『ACE应用构建指南』
作者:阿里云用户mr_wid ,z)NKt# @I6A9do 如果感觉该评测对您有所帮助, 欢迎投票给本文: UO<claV RsfTUb)< 投票标题: 28.[阿里云 ...
- [置顶] 从引爆点的角度看360随身wifi的发展
从引爆点的角度看360随身wifi的发展 不到一个月的时间,随身wifi预定量就数百万.它的引爆点在哪里,为什么相同的产品这么多它却能火起来,通过对随身wifi的了解和我知识层面分析,主要是因为随身w ...
- 站在Java的角度看LinkedList
站在Java的角度看,玩队列不就是玩对象引用对象嘛! public class LinkedList<E> implements List<E>, Deque<E> ...
- 从源码的角度看 React JS 中批量更新 State 的策略(下)
这篇文章我们继续从源码的角度学习 React JS 中的批量更新 State 的策略,供我们继续深入学习研究 React 之用. 前置文章列表 深入理解 React JS 中的 setState 从源 ...
- 从线程模型的角度看Netty的高性能
转载:Netty(二) 从线程模型的角度看 Netty 为什么是高性能的? 传统 IO 在 Netty 以及 NIO 出现之前,我们写 IO 应用其实用的都是用 java.io.* 下所提供的包. 比 ...
- INDEX--从数据存放的角度看索引2
在上次<INDEX--从数据存放的角度看索引>中,我们说到"唯一非聚集索引"和“非唯一非聚集索引”在存储上有一个明显的差别:唯一非聚集索引的非叶子节点上不会包含RID的 ...
- 从JDK源码角度看Short
概况 Java的Short类主要的作用就是对基本类型short进行封装,提供了一些处理short类型的方法,比如short到String类型的转换方法或String类型到short类型的转换方法,当然 ...
随机推荐
- Linux平台开发指南
声明:以下内容摘自http://www.me115.com/post/25.html 以下技术和工具是Linux平台下工作的基础,熟练掌握: C++ 工作语言,重要性不言而喻: 入门: <C++ ...
- 魅族MX2去除smartbar教程
首先确认一点,魅族Smartbar的推出,是敢于创新,大胆向前的做法.在软件兼容的情况下,Smartbar确实提高单手操作的便利,而且和flymeOS整体性融合度比较好. 但是,往往事与愿违,现实中众 ...
- JSON数据的使用
JSON (JavaScript Object Notation)一种简单的数据格式,比xml更轻巧. JSON 是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON ...
- JavaScript倒计时
倒计时: 1.设置一个有效的结束日期 2.计算剩余时间 3.将时间转换成可用的格式 4.输出时钟数据作为一个可重用的对象 5.在页面上显示时钟,并在它到达0时停止 <div id="c ...
- nginx配置返回文本或json
有些时候请求某些接口的时候需要返回指定的文本字符串或者json字符串,如果逻辑非常简单或者干脆是固定的字符串,那么可以使用nginx快速实现,这样就不用编写程序响应请求了,可以减少服务器资源占用并且响 ...
- 2014 39th ACM-ICPC 北京赛区 总结
万万没想到,拿金了. 在经历了西安赛区的打铁经历,感觉我们已经很坦然了.怎么说呢,虽说有阴影,但那也是成长的一步.我在西安打铁之后跟队友跟姐姐说过“如果北京是铜或者铁,我就退役”.记得曾经,很多人问我 ...
- maven学习(下)利用Profile构建不同环境的部署包
接上回继续,项目开发好以后,通常要在多个环境部署,象我们公司多达5种环境:本机环境(local).(开发小组内自测的)开发环境(dev).(提供给测试团队的)测试环境(test).预发布环境(pre) ...
- 查看机器上安装的jdk能支持多大内存
命令:java -Xmx1024m -version C:\Users\maite>java -Xmx1024m -version java version "1.8.0_31&quo ...
- linux系统的初化始配置
一.网络的初始化 1.ip地址的修改(临时生效) 使用ifconfig命令 ifconfig 网卡名 ip地址 子网掩码 [root@localhost /]# ifconfig eno1677773 ...
- JS 模块化和打包方案收集
1.这里想讨论的是拆分规则,不是在问哪个工具怎么使用.2.这里没有在想找正确答案,因为感觉这个问题要结合具体业务场景. 随着项目开发越来越大,一开始代码全打包到一个文件的方式,让文件越来越大,接下来要 ...