天天看點

【Go語言】【15】GO語言的面向對象

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,如需轉載請自行聯系原作者