2016-10-25 1 views
5

Also ich habe dieses Beispiel hier: Go PlaygroundGolang: Typ zuweisen mit einer anderen Struktur

package main 

import (
    "fmt" 
) 

type Circle struct{} 

func (c Circle) Something() { 
    fmt.Println("something") 
} 

type Rectangle struct { 
    Circle 
} 

func (a Rectangle) SomethingElse() { 
    fmt.Println("SomethingElse") 
} 

type Form Rectangle 

func main() { 
    c := Form{} 
    c.Circle.Something() 
    c.SomethingElse() 
} 

Ich verstehe nicht, warum ich Circle, Something aus den eingebetteten nennen kann, aber Somethingelse nicht nennen vom Rectangle innerhalb der Form Typ. Ich verstehe auch nicht, welchen Nutzen ich bekomme, wenn ich einen Typ eines anderen Typs deklariere, wie hier in Form.

Antwort

8

Dies:

type Form Rectangle 

Erstellt einen neue Typ Form genannt, mit Rectangle als Art zugrunde liegen.

Das bedeutet, dass die Felder Rectangle (die eine Struktur ist) auch für Form definiert werden.

Aber Methoden sind an einen bestimmten Typ gebunden. Wenn Sie einen neuen Typ erstellen (Form), verfügt dieser neue Typ über keine der Methoden des zugrunde liegenden Typs. Daher können Sie c.SomethingElse() nicht als SomethingElse() aufrufen. Dies ist eine Methode des Typs Rectangle.

c.Circle.Something() funktioniert, weil c.Circle ein Feld vom Typ ist Circle und Something() ist ein Verfahren des Circle Typs.

Wenn Sie die Rectangle.SomethingElse() Methode aufgerufen werden soll, setzt voraus, dass ein Wert vom Typ Rectangle (der Empfängertyp ist Rectangle). Da zugrunde liegende Typ von FormRectangle ist, können Sie einfach einen Wert von Rectangle von einem Wert vom Typ Typ erhalten Form eine einfache Art mit conversion:

Rectangle(c).SomethingElse() // This works 

Der Vorteil eine neue Art zu schaffen, besteht darin, dass so können Sie erstellen/füge deine eigenen Methoden hinzu. Ein gängiges Beispiel ist die Implementierung der sort.Interface Schnittstelle. Nehmen wir an, Sie haben ein Stück von etwas, z. []Rectangle oder ein Stück eines Typs, auf den Sie keine Kontrolle haben (weil es Teil eines anderen Pakets ist - und Methoden für einen Typ können nur im selben Paket definiert werden). Wenn Sie diese Scheibe sortieren möchten, erstellen Sie eine neue, für die Sie Methoden definieren können, die Methoden der sort.Interface, z.B .:

type SortRectangle []Rectangle 

func (s SortRectangle) Len() int   { return len(s) } 
func (s SortRectangle) Less(i, j int) bool { return s[i] <some-logic> s[j] } 
func (s SortRectangle) Swap(i, j int)  { s[i], s[j] = s[j], s[i] } 

Die sort.Sort() Funktion ist in der Lage alle Werte zu sortieren, die sort.Interface implementieren. Die []Rectangle nicht, aber wir haben gerade einen neuen Typ SortRectangle erstellt, die dies tut.Und wenn wir einen Wert vom Typ []Rectangle haben, können wir ihn in SortRectangle umwandeln, weil ersterer der zugrundeliegende Typ des letzteren ist, und indem wir eine Umwandlung machen, haben wir einen Wert vom Typ SortRectangle, der an sort.Sort() übergeben werden kann, um haben sie nach:

rs := []Rectangle{} 
// Sort rs: 
sort.Sort(SortRectangle(rs)) 

Beachten sie, dass eine Umwandlung wie die oben SortRectangle(rs) nur die Informationen Laufzeittyp ändert, ändert es nicht die Speicher Darstellung rs, so ist es pefectly sicher und effiziente.

Wenn der neue Typ die Methoden des Typs "alt" haben soll, verwenden Sie die Einbettung. Siehe Ainar-Gs Antwort. In der Tat haben Sie dies bereits von Circle in Rectangle Einbetten: die Art Rectangle eine Methode hat Something(), weil Something() ein Verfahren zur Herstellung Circle ist:

Rectangle{}.Something() // Prints "something" 
+0

Danke für die tolle Erklärung! – simplebird

1

Die ganze (und einzige) Grund type Form Rectangle zu tun ist, eine definieren neu Typ mit verschiedenen Methoden. In Ihrem Beispiel: Keine Methoden. c ist ein Formular und hat keine Methoden, es ist nur raison d'être nicht mit einer SomethingElse() Methode.

Aber ein Form bettet noch einen Kreis, der als c.Circle zugänglich ist und bei dem ein Circle ist so obviousely es hat das Verfahren Something().

3

Eine einfache Regel in Go. Wenn Sie den Typ der Methoden wollen, tun

type A struct { B } 

und wenn Sie das tun nicht wollen Methoden der Typ des, tun

type A B 

Warum brauchen wir die zweite Form? Schnittstellen, zum Beispiel. Manchmal wir nicht wollen einen Wert, um eine Schnittstelle zu erfüllen, wie here. Zu anderen Zeiten brauchen Sie nur die Typen und nicht ihre Methoden.

Go gibt Ihnen die Möglichkeit, den gleichen Typ, aber mit einer leeren Methode zu erhalten.

Verwandte Themen