總結兩點:
- 在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()方法。
*/
}
