理解Go的多態實現


總結兩點:

  • 在Go中,定義一個interface類型,該類型說明了它有哪些方法。使用時,在函數中,將該interface類型作為函數的形參,任意一個實現了interface類型的實參都能作為該interface的實例對象。Go中沒有implements關鍵字,與Java的實現多態相比,Go的組合更加靈活。
  • Go語言中沒有繼承,只有組合,可通過組合達到“繼承”方法的目的。

先看一個例子:

/**
 * Animal 三個接口:fly(), swim() 和 run(),如果實現Animal,需要同時實現三個接口。
 */
public interface Animal {
    public void fly();
    public void swim();
    public void run();
}

class Dog implements Animal {
    @Override
    public void fly() {
        System.out.println("Dog can not fly");
    }

    @Override
    public void swim() {
        System.out.println("Dog can not swim");
    }

    @Override
    public void run() {
        System.out.println("Dog can run");
    }
}

class Fish implements Animal {
    @Override
    public void fly() {
        System.out.println("Fish can not fly");
    }

    @Override
    public void swim() {
        System.out.println("Fish can swim");
    }

    @Override
    public void run() {
        System.out.println("Fish can not run");
    }
}

再來看Go的實現:

type Animal1 interface {
	fly()
	swim()
	run()
}

type Dog1 struct {
}

func (d Dog1) run() {
	fmt.Println("dog can run")
}

type Fish struct {
}

func (f Fish) swim() {
	fmt.Println("fish can swim")
}

可以看到,Go中實現需要的功能更靈活。這是多個實現類之間的比較,實現更加靈活。再看類似於“父子”之間的繼承。

import (
	"fmt"
	"reflect"
)

type Base struct {
	// nothing
}

func (b *Base) ShowA() {
	fmt.Println(reflect.TypeOf(b))
	fmt.Println("showA")
	b.ShowB()
}
func (b *Base) ShowB() {
	fmt.Println(reflect.TypeOf(b))
	fmt.Println("showB")
}

func (b *Base) ShowC() {
	fmt.Println(reflect.TypeOf(b))
	fmt.Println("showC")
}
//Derived 通過組合Base結構體,實現了偽繼承,即擁有了ShowA和ShowB方法
type Derived struct {
	Base
}
//Derived 自己實現了ShowB方法,但不會自動做類型轉換
func (d *Derived) ShowB() {
	fmt.Println(reflect.TypeOf(d))
	fmt.Println("Derived showB")
}

type NewBase Base

func main2() {
	d := Derived{Base{}}
	d.ShowA()  //Derived通過組合,有了ShowA()方法
	/**
	*main.Base
	showA
	*main.Base
	showB
	上述代碼執行結果不會輸出“Derived showB”,因為Go中沒有繼承的概念,只有組合.
	上面的Derived包含了Base,自動的含有了Base的方法,因為其不是繼承,所以不會根據具體傳入的對象而執行對應的方法。
	*/
	d.ShowB()
	/**
	*main.Derived
	Derived showB
	*/

	d.Base.ShowB()
	/**
	*main.Base
	showB
	d 通過組合獲取了Base的方法 ShowB. 但如果d要調取Base的ShowB()方法(與d的ShowB()方法重復),需要顯示調用Base.
	*/
	d.ShowC()
	/**
	*main.Base
	showC
	d 通過組合獲取了Base的方法 ShowC.
	 */
	b := Base{}
	b.ShowC()
	//b1 := NewBase{}
	//b1.ShowC()  //沒有ShowC()方法
	/**
	上面的代碼中b1不能執行ShowC()函數,因為Golang不支持隱式類型轉換.
	雖然newBase就是Base,但語法上它們是兩種類型,因此newBase不能執行ShowC()方法。
	 */
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM