go中如何實現多型

weixin_33850890發表於2016-04-24

接觸go快半年了, 但是還是屬於那種用到時去搜尋的狀態, 沒有系統的去研究研究

go 是一種強型別的語言,每當我從php切換到go時總有些許的不適應,但是追求優雅,就不應該妥協。

go沒有 implements, extends 關鍵字,所以習慣於 OOP 程式設計,或許一開始會有點無所適從的感覺。 但go作為一種優雅的語言, 給我們提供了另一種解決方案, 那就是鴨子型別看起來像鴨子, 那麼它就是鴨子.

那麼什麼是鴨子型別, 如何去實現呢 ?

接下來我會以一個簡單的例子來講述這種實現方案。

首先我們需要一個超類:

type Animal interface {
    Sleep()
    Age() int
    Type() string
}

必然我們需要真正去實現這些的子類:

type Cat struct {
    MaxAge int
}

func (this *Cat) Sleep() {
    fmt.Println("Cat need sleep")
}
func (this *Cat) Age() int {
    return this.MaxAge
}
func (this *Cat) Type() string {
    return "Cat"
}
type Dog struct {
    MaxAge int
}

func (this *Dog) Sleep() {
    fmt.Println("Dog need sleep")
}
func (this *Dog) Age() int {
    return this.MaxAge
}
func (this *Dog) Type() string {
    return "Dog"
}

我們有兩個具體實現類 Cat, Dog, 但是Animal如何知道Cat, Dog已經實現了它呢? 原因在於: Cat, Dog實現了Animal中的全部方法, 那麼它就認為這就是我的子類。

那麼如何去使用這種關係呢?

func Factory(name string) Animal {
    switch name {
    case "dog":
        return &Dog{MaxAge: 20}
    case "cat":
        return &Cat{MaxAge: 10}
    default:
        panic("No such animal")
    }
}

我們使用具體工廠類來構造具體的實現類, 在呼叫時你知道有這些方法, 但是並不清楚具體的實現, 每一種型別的改變都不會影響到其它的型別。

package main

import (
    "animals"
    "fmt"
)

func main() {
    animal := animals.Factory("dog")
    animal.Sleep()
    fmt.Printf("%s max age is: %d", animal.Type(), animal.Age())
}

來看看我們的輸出會是什麼吧

> Output:
animals
command-line-arguments
Dog need sleep
Dog max age is: 20
> Elapsed: 0.366s
> Result: Success

這就是go中的多型, 是不是比 implements/extends 顯示的表明關係更優雅呢。

相關文章