2011-06-26 38 views
4

如果type T2基於type T1,除了共享相同的數據字段,T1T2之間是否有任何關係?在Go中,如果T2類型基於T1類型,是否有任何類型的從T1到T2的「繼承」?

 
package main 
import "fmt" 

type T1 struct { s string } 
func (v *T1) F1() string { return v.s } 

type T2 T1 
func (v *T2) F2() string { return v.s } 

func main() { 
     var t1 = T1{ "xyz" } 
     var t2 = T2{ "pdq" } 
     s0 := t2.F1()     // error - expected ok 
     s1 := ((*T1)(&t2)).F1()   // ok - expected 
     s2 := ((*T2)(&t1)).F2()   // ok - not expected 
     fmt.Println(s0, s1, s2) 
} 

這裏我的理解是缺乏

  1. 一直希望T2將繼承T1的方法,但這種情況並非如此。

  2. 期待T2可以強迫T1,因爲它是從T1

  3. 衍生感到驚訝的是T1可以強迫T2,但事實如此。

  4. 看來T1T2之間的關係是完全對稱的 - 儘管實際上是從另一個實際導出的,但我無法找到任何破壞對稱性的東西 - 或者這是幻覺?

(注:我不批評或判斷 - 我完全尊重做出的決定 - 只是驗證我明白了什麼是那裏,對我來說是反直覺的 - 我相信我不是唯一一個!)

回答

4

Go不支持面向對象的類型繼承。

Is Go an object-oriented language?

Why is there no type inheritance?

的方法被綁定到單個特定的類型。

A method declaration將 標識符綁定到方法。該方法是 表示綁定到基類型,並且 僅在類型爲 的選擇器中可見。

你可以種T1T2之間convert

x可以converted鍵入 T [時] x的類型和T具有 相同基礎類型。

例如,

package main 

import (
    "fmt" 
) 

type T1 struct{ i int } 

func (t T1) String() string { return "T1" } 

type T2 T1 

func (t T2) String() string { return "T2" } 

func main() { 
    t1 := T1{1} 
    t2 := T2{2} 
    fmt.Println(t1, t2) 
    c1 := T1(t2) 
    c2 := T2(t1) 
    fmt.Println(c1, c2) 
    t1 = T1(c2) 
    t2 = T2(c1) 
    fmt.Println(t1, t2) 
} 

Output: 
T1 T2 
T1 T2 
T1 T2 
+0

所以當你說'輸入T2 T1'時,發生了什麼事情是'T1'的結構被複製爲'T2'的結構,並且它們具有相同的結構,它們可以重新對換,否則'T2'與'T1'沒有任何關係 –

+0

是的。有很多轉換規則。對於這個特定的規則,「T1」和「T2」具有相同的底層類型這一事實意味着它們也具有相同的內存大小,佈局和內容。 – peterSO

0
s2 := ((*T2)(&t1)).F2()   // ok - not expected 

的作品,因爲你投它鍵入T2,因此它允許F2。所以它有望運作。 F2函數然後在您的T2對象t1上調用,該對象返回t1.s

s0 := t2.F1()     // error - expected ok 

對於這一塊,我不能告訴你肯定的,但只能給你我的想法可行,以及:

F1是T1類型的方法。由於t2不是T1類型,因此不能在t2上調用F1。所以,如您所述,只有數據字段是共享的,而不是這些類型的方法。

另請參閱Go for C++ programmers,其中規定:

方法是在命名類型定義。如果將該值轉換爲其他類型,則新值將具有新類型的方法,而不是舊類型。

0

我可以解釋爲什麼T2沒有方法T1。想象一下,你需要用兩種不同的方式對T類型的數據進行排序。一種方法是默認設置,因此您在T中實施Len,LessSwap方法。您可以撥打sort.Sort(data)並以默認方式對數據進行排序。但如何對數據進行不同的分類?

您編寫type SortDifferently T並執行Len,LessSwap方法爲SortDifferently類型。如果SortDifferently的所有方法都是T,則不能這樣做,因爲Go沒有方法重寫。但是,如果沒有繼承,您現在可以編寫sort.Sort((SortDifferently)data)以不同方式對數據進行排序。

這是Go的做事方式。習慣並不容易。

+0

「Go沒有方法覆蓋」 - 我想這就是了。 –

+0

事情是Go * does *有方法陰影。如果使用'SortDifferently struct {T}',它會將所有方法從'T'轉發到'SortDifferently',並且仍允許您使用專門在'SortDifferently'上編寫的方法來映射這些名稱。您仍然可以調用「T」版本,即使在影子方法中也是如此。我不知道他們爲什麼不接受'SortDifferently T'類型的情況。 – matthias

0

不知道它是否會幫助你,但看看例如"Go for C++ programmers",在「接口」部分描述的「匿名字段」 - 看起來他們提供了一些看起來像子類的東西。

但無論如何,通過Go上的教程閱讀,我開發了一個想法,Go的作者決定讓程序員避開構建繼承鏈並改用嵌入/委派。

相關問題