2013-08-04 68 views
1

我是一名Java程序員,學習在Go中編程。到目前爲止,我非常喜歡這種語言。比Java多得多。Golang:當你有多重繼承時,接口的要點是什麼

但有一點我有點困惑。 Java有接口,因爲類只能從一個類繼承。由於Go允許多重繼承,接口的意義何在?

+1

依我拙見,答案http://stackoverflow.com/questions/8531292/why-use-interfaces-multiple -inheritance-vs-interfaces-interfaces-benefits-of-interfaces也適用於此。 – kush

+0

接口和多重繼承是相關的,但只是相切。 Java的接口不能代替多繼承。接口允許您將合同與實施分開。多重繼承的用途有限,但會導致更多的麻煩和非直觀的,難以調試的問題,而不是它的價值,恕我直言。 –

+0

@JimGarrison,你能否詳細說明一下?接口只是告訴'要做什麼',而通過繼承,你還可以獲得有關'如何做'的信息,並可以選擇重寫該行爲。繼承如何導致麻煩,以及在什麼情況下接口會更好。一個例子真的有幫助! – tldr

回答

10

多態性

接口允許功能具有可以採取不同的結構作爲自變量的「佔位符」參數。例如,如果結構Man,Woman,Child實現了Interface Human,那麼帶有Human參數的方法可以將任何結構Man,Woman,Child作爲參數。因此,只要接口參數實現了接口中定義的所有函數,接口參數就可以「變形」爲任何作爲參數傳遞的結構。

這很重要,因爲接口是實現Go中多態性的唯一方法,因爲它沒有繼承。因此,如果Man'擴展'Human(通過將它作爲一個匿名字段),那麼以Human作爲論點的任何方法都無法將Man作爲參數。

我的困惑源於繼承也是實現Java中的多態性的一種方式,我也認爲這種情況也是如此。我站好了!

1

如果超類型X是一個接口,維護代碼的人就會立即知道它沒有方法實現。如果超類型Y是一個抽象類,那麼維護代碼的人必須檢查是否有方法實現。所以這是一個文檔/維護/可讀性的東西。

0

類可以從多個類文件繼承和實現。

除非我誤解:

public class MyClass extends MySuperClass implements MyInterface, MySecondInterface 

接口的一點是,允許一個完全抽象類。因此抽象說明沒有定義單個方法。 當我需要用相同的基本結構創建幾個抽象類時,我會使用一個接口。然後,我可以創建擴展抽象類的類的實例,從而實現接口。

這是通過接口java.util.Collection完成的,一些類如java.util.ArrayListjava.util.Stack實現了該接口。通過這種方式,您可以將各種列表項目存儲在一個集合中。這就是爲什麼ArrayList有一個方法addAll(Collection<? extends E> c)

你可以說它就像是向後兼容簡單的對象。

9

Go中的接口與Java中的接口非常不同。

在Java類有正式同意實現一個接口:

public class Foo implements iFoo 

在圍棋用戶類型通過簡單地這樣實現的接口。然後

一個功能或屬性可以定義的期望是什麼:

func DoSomething(r io.Reader) { 
    buf := make([]byte, 128) 
    n, err := r.Read(buf) 
    ... 
} 

DoSomething功能都可以通過任何實現在io.Reader界面發現Read功能,而不事情知道或關心關於界面。主叫方有責任確保它通過實現接口。這在編譯時檢查。

我們可以更進一步。我們可以定義我們自己的接口:

type MyInterface interface { 
    io.Reader // Include Reader interface 
    Seek(int) error // Include my own function 
} 
func DoSomething(r MyInterface) { 
    buf := make([]byte, 128) 
    n, err := r.Read(buf) 
    ... 
} 

圍棋也不同,因爲它不具有對象類型。任何聲明類型的用戶,無論是基於整數,字符串,結構,數組,切片,通道等,都可以附加方法。

Go也沒有你通常習慣的典型的類繼承,但它確實有一些非常接近的事情。

重新聲明類型:

type Num int 

func (n Num) Print() { 
    print(n) 
} 

type Number Num 

func (n Number) Print() { 
    Num(n).Print() 
} 

匿名字段:

type Foo struct { 
    sync.Mutex 
} 

func main() { 
    f := Foo{} 
    f.Lock() 
    // ... 
    f.Unlock() 
}