【Go语言】【15】GO语言的面向对象
GO作者如是说:“是,也不是。”
正如前面所说:GO是一种面向类型的语言,它有类型和方法,但没有类的概念,程序员可以用一种面向对象的风格(或者说是方式)来编程,下面我们从封装性、继承性和多态性三大面向对象的特性谈谈GO语言
1、封装性
面向对象的语言中,“类”是基本单位,它把属性、方法局限在“类”中,并对外提供公共方法让使用者操作对象。当然这一过程离不开修饰符:public、protected、private等。
GO语言如何实现封装性呢?它是通过结构体(struct)和为类型添加方法的方式实现的。
例如,封装一个矩形(Rect)类,试想调用者会对矩形类做什么操作呢?无非就是看看它的面积、周长之类的信息,那么按照面向对象的编程思想来说,只要向使用者暴露getArea()、getPerimeter()方法即可,使用者无须接触到矩形的长和宽。
/**
* 定义一个结构体,里面有两个成员length和width
*/
type Rect struct {
length, width int
}
接下来为结构体定义两个方法getArea()和getPerimeter(),分别用来读取矩形的面积和周长
/**
* 获取矩形的面积
*/
func (r *Rect) GetArea() int {
return r.length * r.width
}
/**
* 获取矩形的周长
*/
func (r *Rect) GetPerimeter() int {
return (r.length + r.width) * 2
}
为了让该包之外的函数调用到GetArea()和GetPerimeter(),所以这里函数的首字母大写。同时为了结构体初始化更面向对象些,再定义一个用于初始化结构体的方法NewRect()
/**
* 初始化结构体Rect
*/
func NewRect(length, width int) *Rect {
return Rect{length, width}
}
经过这样的封装,使用者可以以面向对象的方式调用Rect了 :)
/**
* 使用者先引入Rect.go的路径
*/
import (
"cube"
"fmt"
)
/**
* 通过cube调用NewRect()生成*Rect对象
*/
func main() {
r := cube.NewRect(10, 20)
fmt.Println("面积:", r.GetArea(), " 周长:", r.GetPerimeter())
}
【备注】:
Rect.go和测试main.go路径结构如下
其中Rect.go所属包为cube、main.go所属包为main
执行程序,运行结果如下:
2、继承性
rect结构体定义两个方法,分别用于获取面积和周长,cube结构体也定义了两个方法,一个是获取体积,另一个重写父结构体rect的获取周长:
(1)在cube目录下创建rect.go文件,里面写rect代码
// 让rect结构体在cube包内
package cube
// 定义rect结构体
type rect struct{
length, width int
}
/**
* 获取矩形的面积
*/
func (r Rect) GetArea() int {
return r.length * r.width
}
/**
* 获取矩形的周长
*/
func (r Rect) GetPerimeter() int {
return (r.length + r.width) * 2
}
(2)在cube目录下创建cube.go文件,里面写cube代码
// 让Cube结构体在cube包内
package cube
// 由于Cube结构体需要对外,所以首字母大写
type Cube struct {
Rect // 这里通过嵌套结构体实现GO的继承
height int
}
/**
* 获取立方体的体积
*/
func (c Cube) GetVolume() int {
return c.Rect.length * c.Rect.width * c.height
}
/**
* 重写父类获取周长方法
*/
func (c Cube) GetPerimeter() int {
return (c.Rect.length + c.Rect.width + c.height) * 4
}
/**
* 为了更象面向对象编程些,这里定义了一个方法获取Cube对象
*/
func NewCube(length, width, height int) Cube {
return Cube{Rect: Rect{length, width}, height: height}
}
(3)在src目录下创建main.go文件,该文件与cube目录同级,里面写测试代码
// 让main()方法的包为main
package main
import (
"cube" // 由于要用到上面定义的Cube结构体,所以需要引入Cube结构体所属包
"fmt"
)
func main() {
var c cube.Cube = cube.NewCube(10, 20, 30) // 通过包名调用cube.go定义的对外方法NewCube()
fmt.Println("面积:", c.GetArea(), ",体积:", c.GetVolume()) // 通过变量c调用相应方法
fmt.Println("周长:", c.GetPerimeter())
}
执行go run main.go,得到执行结果:
从运行结果可以看到,尽管Cube没有定义GetArea()方法,但通过c.GetArea()的确调用到了同时并打印出结果;由于Cube重写了GetPerimeter()方法,从结果来看c.GetPerimeter()执行的是Cube的GetPerimeter()就去。
从该例也不难看出GO的继承性是通过结构的嵌套来实现的
3、多态性
多态意味着一个对象有多重特征,在特定的情况下表现不同的状态,即对应着不同的方法
Mp3和Iphone都实现了USB接口,并分别实现接口USB定义的方法,当面向对象如此调用时:
USB u1 = new Mp3();
u1.connect(); // 打印出“mp3”
USB u2 = new Iphone();
u2.connect(); // 打印出“iphone”
同样的接口(USB)对象(u1, u2),由于实现类不同,调用相同的方法(connect()),最终的效果是不同的,这就是多态的作用,一般用于“控制反转”。
那么Go呢?
Go可以通过Interface、struct模拟实现多态
在src下创建usb目录,在usb目录下创建usb.go文件,里面定义USB接口
// 把接口USB放在usb包中
package usb
// 定义USB接口,里面只有一个Connect()方法
type USB interface {
Connect()
}
在usb目录下创建mp3.go文件,里面定义Mp3结构体,并为该结构体增加Connect(),这样就相当于实现了接口USB
// 把Mp3结构体放在usb包中
package usb
import (
"fmt"
)
// 定义Mp3空结构体
type Mp3 struct {
}
// 为Mp3增加Connect()方法,这样就缺省实现了USB接口
func (m Mp3) Connect() {
fmt.Println("mp3")
}
同样,在usb目录下创建iphone.go文件,里面定义Iphone结构体
// 把Iphone结构体放在usb包中
package usb
import (
"fmt"
)
// 定义Iphone空结构体
type Iphone struct {
}
// 为Iphone增加Connect()方法,这样就缺省实现了USB接口
func (i Iphone) Connect() {
fmt.Println("iphone")
}
下面演示GO语言的多态性:
在src目录下创建main.go文件,该文件与usb目录同级,里面写测试代码
package main
import (
"usb"
)
func main() {
var m usb.USB = usb.Mp3{}
m.Connect()
var n usb.USB = usb.Iphone{}
n.Connect()
}
执行程序,运行结果如下:
【备注】:
关于本文的演示代码可以在本章节源代码处下载
本文出自 “青客” 博客,请务必保留此出处http://qingkechina.blog.51cto.com/5552198/1675872
Excelize 发布 2.7.1 版本,Go 语言 Excel 文档基础库 Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,2023年4月10日,社区正式发布了 2.7.1 版本,该版本包含了多项新增功能、错误修复和兼容性提升优化。
Windows平台Go语言环境搭建 “当时,没有一个团队成员知道 Go,但在一个月内,每个人都在用 Go 编写,我们正在构建端点。正是它的灵活性、易用性以及 Go 背后的真正酷的概念(Go 如何处理本机并发、垃圾收集,当然还有安全+速度)帮助我们在构建过程中参与其中。还有,谁能打败那个可爱的吉祥物!— Jaime Enrique Garcia Lopez,Capital One 高级软件开发经理
相关文章
- Go语言之JSON序列化(二十三)
- 2022-09-18:以下go语言代码输出什么?A:1;B:15;C:panic index out of range;D:doesn’t compile。 p
- Go语言开发规范实践指南
- 2022-10-22:以下go语言代码输出什么?A:moonfdd1;B:编译错误;C:运行时 panic。 package main import “fmt“
- 「Go工具箱」go语言csrf库的使用方式和实现原理
- Go 语言短变量声明的“坑”
- Go 快速入门篇(三):单元测试、问题定位及代码调试
- GO语言开篇-Go语言急速入门(基础知识点)| 青训营笔记
- Go语言技巧 - 17.【Go工程化测试】业务项目中的Go单元测试心得
- 使用Go语言开发的云存储网盘项目开源哦
- Naabu:一款基于Go语言开发的快速端口扫描工具
- Go-标准库-os(二)
- Go语言变量的声明(使用var关键字)
- Go语言inject库:依赖注入
- Go从入门到精通(一)go语言初识详解编程语言
- 使用Go语言来操作Oracle数据库(go语言oracle)
- Go语言使用定时器实现任务队列
- 使用源码安装Go语言
- Go语言函数值传递和引用传递
- Go语言解码未知结构的JSON数据
- 精通Go语言开发Redis应用(go语言redis开发)
- 编程新精英:Go语言 Redis开发(go语言redis开发)
- 轻松搞定Go语言连接MySQL(go连接mysql)
- 基于Linux环境下GO语言编译实践(linuxgo编译)
- 以Go语言操作MySQL:轻松运行数据库各种查询(go语言mysql)
- 使用Go语言实现Redis数据库(用go实现redis)
- 请求简单而快速用Go编写的Redis请求测试(用go写的redis)
- 新技术Go语言解析Oracle数据库日志(go解析oracle日志)
- 数据库Go语言实现监控Oracle数据库(go监听oracle)
- Go语言操作Oracle数据库技术实践(go操作oracle)
- ODBC数据驱动程序连接Oracle数据库Go语言之旅(go使用oracle)
- 语言Oracle中发挥神奇作用的Go语言(oracle中有go)
- Go语言并发技术详解