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路徑結構如下
<a href="http://s3.51cto.com/wyfs02/M01/6F/CE/wKioL1WpHPnTstkAAAAnAJYeePs897.jpg" target="_blank"></a>
其中Rect.go所屬包為cube、main.go所屬包為main
執行程式,運作結果如下:
<a href="http://s3.51cto.com/wyfs02/M02/6F/CE/wKioL1WpHarwUCv-AABTfzOr2QE794.jpg" target="_blank"></a>
2、繼承性
<a href="http://s3.51cto.com/wyfs02/M01/6F/CF/wKioL1Wpt9uz-QZHAABs_WAb8pQ174.jpg" target="_blank"></a>
rect結構體定義兩個方法,分别用于擷取面積和周長,cube結構體也定義了兩個方法,一個是擷取體積,另一個重寫父結構體rect的擷取周長:
(1)在cube目錄下建立rect.go檔案,裡面寫rect代碼
// 讓rect結構體在cube包内
package cube
// 定義rect結構體
type rect struct{
* 擷取矩形的面積
func (r Rect) GetArea() int {
* 擷取矩形的周長
func (r Rect) GetPerimeter() int {
(2)在cube目錄下建立cube.go檔案,裡面寫cube代碼
// 讓Cube結構體在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
"cube" // 由于要用到上面定義的Cube結構體,是以需要引入Cube結構體所屬包
"fmt"
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,得到執行結果:
<a href="http://s3.51cto.com/wyfs02/M00/6F/D1/wKiom1WpuiywwgvAAABG6TF_56Q376.jpg" target="_blank"></a>
從運作結果可以看到,盡管Cube沒有定義GetArea()方法,但通過c.GetArea()的确調用到了同時并列印出結果;由于Cube重寫了GetPerimeter()方法,從結果來看c.GetPerimeter()執行的是Cube的GetPerimeter()就去。
從該例也不難看出GO的繼承性是通過結構的嵌套來實作的
3、多态性
多态意味着一個對象有多重特征,在特定的情況下表現不同的狀态,即對應着不同的方法
<a href="http://s3.51cto.com/wyfs02/M01/6F/D4/wKiom1Wp5cjDZPmhAACjxTnjA4U819.jpg" target="_blank"></a>
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包中
// 定義Mp3空結構體
type Mp3 struct {
// 為Mp3增加Connect()方法,這樣就預設實作了USB接口
func (m Mp3) Connect() {
fmt.Println("mp3")
同樣,在usb目錄下建立iphone.go檔案,裡面定義Iphone結構體
// 把Iphone結構體放在usb包中
"fmt"
// 定義Iphone空結構體
type Iphone struct {
// 為Iphone增加Connect()方法,這樣就預設實作了USB接口
func (i Iphone) Connect() {
fmt.Println("iphone")
下面示範GO語言的多态性:
在src目錄下建立main.go檔案,該檔案與usb目錄同級,裡面寫測試代碼
"usb"
var m usb.USB = usb.Mp3{}
m.Connect()
var n usb.USB = usb.Iphone{}
n.Connect()
<a href="http://s3.51cto.com/wyfs02/M02/6F/D4/wKiom1Wp622zkvO8AAA9r_LrKnA061.jpg" target="_blank"></a>
關于本文的示範代碼可以在本章節源代碼處下載下傳
<a href="http://down.51cto.com/data/2365926" target="_blank">附件:http://down.51cto.com/data/2365926</a>
本文轉自qingkechina 51CTO部落格,原文連結:http://blog.51cto.com/qingkechina/1675872,如需轉載請自行聯系原作者