2017-11-06 2 views
-1

Dieser Code nicht korrekt ausgeführt:go Vererbung und Polymorphismus

package main 
import "fmt" 

type Human interface { 
    myStereotype() string 
} 

type Man struct { 
} 

func (m Man) myStereotype() string { 
    return "I'm going fishing." 
} 

type Woman struct { 
} 

func (m Woman) myStereotype() string { 
    return "I'm going shopping." 
} 
func main() { 
    var m *Man 
    m = new (Man) 
    w := new (Woman) 

    var hArr []*Human 

    hArr = append(hArr, m) 
    hArr = append(hArr, w) 

    for n, _ := range (hArr) { 

     fmt.Println("I'm a human, and my stereotype is: ", 
       hArr[n].myStereotype()) 
    } 
} 

Es existiert mit:

tmp/sandbox637505301/main.go:29:18: cannot use m (type *Man) as type *Human in append: 
*Human is pointer to interface, not interface 
tmp/sandbox637505301/main.go:30:18: cannot use w (type *Woman) as type *Human in append: 
*Human is pointer to interface, not interface 
tmp/sandbox637505301/main.go:36:67: hArr[n].myStereotype undefined (type *Human is pointer to interface, not interface) 

Aber dieses läuft richtig (var harr [] * Mensch in var harr [neu geschrieben ] Mensch):

package main 
import "fmt" 

type Human interface { 
    myStereotype() string 
} 

type Man struct { 
} 

func (m Man) myStereotype() string { 
    return "I'm going fishing." 
} 

type Woman struct { 
} 

func (m Woman) myStereotype() string { 
    return "I'm going shopping." 
} 
func main() { 
    var m *Man 
    m = new (Man) 
    w := new (Woman) 

    var hArr []Human // <== !!!!!! CHANGED HERE !!!!!! 

    hArr = append(hArr, m) 
    hArr = append(hArr, w) 

    for n, _ := range (hArr) { 

     fmt.Println("I'm a human, and my stereotype is: ", 
       hArr[n].myStereotype()) 
    } 
} 

Ausgang ist ok:

I'm a human, and my stereotype is: I'm going fishing. 
I'm a human, and my stereotype is: I'm going shopping. 

Und ich verstehe nicht warum. Wie m und w sind Zeiger, warum, wenn ich hArr als ein Array von Zeigern auf Mensch definieren, der Code fehlschlägt?

Vielen Dank für Ihre Erklärung

+3

Go hat keine Vererbung, daher gibt es keinen Polymorphismus vom Typ "ist a". – JimB

+0

Mögliches Duplikat von [Verwenden von Schnittstellen zum Erstellen einer Warteschlange für beliebige Typen] (https://stackoverflow.com/questions/35595810/using-interfaces-to-create-a-queue-for-arbitrary-types) – IanAuld

Antwort

4

Ihr Hauptproblem ist, dass Sie einen Zeiger an eine Schnittstelle verwenden. Meine Antwort auf this question enthält einige Details über den Unterschied. Es genügt zu sagen, dass Zeiger auf Schnittstellen fast immer Fehler sind.

Wenn Sie ein *Man in einem Human (kein *Human) speichern, funktioniert es gut, weil Schnittstellen Zeiger ohne ein Problem speichern können. Im Allgemeinen möchten Sie standardmäßig Zeiger in Schnittstellen speichern, da in Schnittstellen gespeicherte Werte nicht auf Zeigermethoden des gespeicherten Typs zugreifen können. Eine Schnittstelle ist einfach ein Bucket, das einen Typ enthält, und es spielt keine Rolle, ob dieser Typ eine Struktur oder ein Zeiger auf eine Struktur ist. Ein Zeiger zu einer Schnittstelle, auf der anderen Seite ist NICHT eine Schnittstelle, und hat nicht das gleiche implizite Fulfillment-System, das Schnittstellen haben. Es ist ungefähr dasselbe, als ob eine *func() Variable nicht als Funktion verwendet werden kann. Es ist ein Zeiger, keine Funktion.

TL; DR: keine Zeiger auf Schnittstellen verwenden. Es ist fast nie nützlich und spiegelt im Allgemeinen nur ein Missverständnis dessen wider, was Schnittstellen sind.

1

Es kann hilfreich sein, über Interfaces zu denken, die eher einer API-Definition als einem Typ ähneln. Dinge, die die Schnittstelle erfüllen, können bereits Structs oder Zeiger sein, so dass Sie keinen Schnittstellenzeiger verwenden müssen. Wie in this excellent answer angegeben:

Zeiger auf Schnittstellen sind fast nie sinnvoll. Tatsächlich wurde die Go-Laufzeit speziell bei einigen Versionen geändert, um Interface-Pointer (wie bei Strukturpointern) nicht mehr automatisch zu dereferenzieren, um deren Verwendung zu erschweren. In der überwiegenden Mehrzahl der Fälle spiegelt ein Zeiger auf eine Schnittstelle ein Missverständnis darüber wider, wie Schnittstellen funktionieren sollen.