【Go语言】【15】GO语言的面向对象

qingkechina · · 662 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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路径结构如下

wKioL1WpHPnTstkAAAAnAJYeePs897.jpg

其中Rect.go所属包为cube、main.go所属包为main


执行程序,运行结果如下:

wKioL1WpHarwUCv-AABTfzOr2QE794.jpg


2、继承性

wKioL1Wpt9uz-QZHAABs_WAb8pQ174.jpg

聽 聽 聽 聽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,得到执行结果:

wKiom1WpuiywwgvAAABG6TF_56Q376.jpg

聽 聽 聽 聽从运行结果可以看到,尽管Cube没有定义GetArea()方法,但通过c.GetArea()的确调用到了同时并打印出结果;由于Cube重写了GetPerimeter()方法,从结果来看c.GetPerimeter()执行的是Cube的GetPerimeter()就去。

聽 聽 聽 聽从该例也不难看出GO的继承性是通过结构的嵌套来实现的


3、多态性

多态意味着一个对象有多重特征,在特定的情况下表现不同的状态,即对应着不同的方法

wKiom1Wp5cjDZPmhAACjxTnjA4U819.jpg

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()

}

执行程序,运行结果如下:

wKiom1Wp622zkvO8AAA9r_LrKnA061.jpg



【备注】:

关于本文的演示代码可以在本章节源代码处下载



本文出自 “青客” 博客,请务必保留此出处http://qingkechina.blog.51cto.com/5552198/1675872


有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:qingkechina

查看原文:【Go语言】【15】GO语言的面向对象

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

662 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传