slice struct != Scheibe der Schnittstelle implementiert?
Habe ich eine Schnittstelle Model
implementiert durch struct Person
.
Um ein Modell-Beispiel habe ich die folgenden Hilfsfunktionen:
func newModel(c string) Model {
switch c {
case "person":
return newPerson()
}
return nil
}
func newPerson() *Person {
return &Person{}
}
Dem obigen Ansatz ermöglicht es mir, um wieder eine richtig getippte Person-Instanz (kann leicht hinzufügen neuer Modelle später mit dem gleichen Ansatz).
Wenn ich versuchte, etwas ähnliches zu tun für die Rücksendung eine Scheibe von Modellen, bekomme ich eine Fehlermeldung. Code:
func newModels(c string) []Model {
switch c {
case "person":
return newPersons()
}
return nil
}
func newPersons() *[]Person {
var models []Person
return &models
}
Gehen, beschwert sich mit: cannot use newPersons() (type []Person) as type []Model in return argument
Mein Ziel ist die Rückgabe einer Scheibe was auch immer das Modell, der Typ wird verlangt (ob []Person
, []FutureModel
, []Terminator2000
, w/e). Was bin ich, und wie kann ich richtig die Implementierung einer solchen Lösung?
- Ein Segment unterscheidet sich von einem array in Gehen. Da waren Sie wirklich sprechen, Scheiben, habe ich Ihren Beitrag bearbeitet um dies zu reflektieren.
- Stephen, vielen Dank, geschätzt 🙂
- Haben Sie jemals herausfinden? Ich bin versucht, das gleiche zu tun, so dass ich nicht wiederholen Sie eine Tonne von code für meine
/api/{collection}
. Ich habe es funktioniert für alles, außer für die index-Funktion, die Lesen muss in eine Scheibe. - Ich kann mich nicht erinnern, was ich am Ende tun hier, und ich habe nicht gespielt w/ Gehen in eine Weile. Sorry, ich kann nicht mehr Hilfe.
- Kontravarianz (oder ist das Kovarianz -?) schlägt wieder zu!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist sehr ähnlich zu einer Frage, die ich gerade beantwortet: https://stackoverflow.com/a/12990540/727643
Die kurze Antwort ist, dass Sie korrekt sind. Eine Scheibe von Strukturen ist nicht gleich eine Scheibe ein interface struct implementiert.
Einen
[]Person
und ein[]Model
haben unterschiedliche Speicher-layouts. Dies ist, weil die Art, Sie sind die Scheiben haben unterschiedliche Speicher-layouts. EinModel
ist ein interface-Wert, was bedeutet, dass im Speicher es ist zwei Worte, die in der Größe. Ein Wort für die Art von Informationen, die andere für die Daten. EinPerson
ist eine Struktur, deren Größe hängt von der darin enthaltenen Felder. Um die Konvertierung von[]Person
zu einem[]Model
, müssen Sie die Schleife über das array und nicht eine Typ-Konvertierung für jedes element.Seit dieser Umstellung ist eine O(n) Betrieb und würde in eine neue Scheibe erstellt, Gehen Sie weigert sich, es zu tun, implizit. Sie können es tun, explizit mit dem folgenden code.
Und als dskinner hingewiesen, werden Sie wahrscheinlich wollen ein Stück von Zeigern und nicht einen Zeiger auf eine Scheibe. Ein Zeiger auf einer Scheibe ist normalerweise nicht erforderlich.
A
die Umsetzung der von mir gewünschten SchnittstelleB
ich wäre in der Lage zu verwenden, eine ScheibeA
s, als eine ScheibeB
s (nach allen, die Speicher-Struktur ist identisch, da Sie beide Schnittstellen). Ich war enttäuscht zu entdecken, ich kann nicht 🙁Vielleicht ist das ein Problem mit dem Rückgabetyp
*[]Person
, wo Sie eigentlich sein sollten[]*Person
so zu verweisen, dass jeder index, der slice ist eine Referenz auf einPerson
, und wo eine Scheibe[]
ist in sich eine Referenz auf ein array.Schauen Sie sich das folgende Beispiel:
Als Stephen die Frage bereits beantwortet und du bist ein Anfänger ich betonen, auf zu beraten.
Einen besseren Weg, von der Arbeit mit go-Schnittstellen nicht über einen Konstruktor verfügen, der Rückkehr
die Schnittstelle, wie Sie eingesetzt werden könnten, um von anderen Sprachen, wie java, aber haben
ein Konstruktor für jedes Objekt, unabhängig, wie Sie die Schnittstelle implementieren implizit.
Statt
sollten Sie tun
mit
Person
undPolitician
sowohl die Umsetzung der Methoden derModel
.Sie können immer noch
Person
oderPolitician
überall, woModel
ist akzeptiert, aber Sie können auch andere Schnittstellen implementieren.
Mit Ihrer Methode würden Sie begrenzt
Model
bis Sie eine manuelle Umstellung aufeine weitere Schnittstelle geben.
Angenommen ich habe eine
Person
implementiert die MethodeWalk()
und einModel
implementiertShowOff()
folgende nicht funktionieren würde, geradlinig:Allerdings würde dies:
/api/{collection}
dynamisch interagieren w/ die angeforderte Sammlung. Können Sie vorschlagen, eine alternative Lösung ohne explizit die Prüfung der angeforderten Auflistung über mehrere Funktionen? Ich denke, was ich Suche, ist ein Weg, um anzugeben, ein generischer Rückgabetyp, ohne Verlust von know-how der it-Typ.interface{}
, das problem ist, dass Sie dann tun müssen, runtime-type-Behauptungen anstelle von compiler Typ-überprüfung. Eine generische Lösung fürname -> object
ohne Laufzeit Behauptungen ist nur möglich, die Verwendung von Generika, die gehen nicht unterstützt. Also, wenn Sie dies tun, Sie haben zu Leben, mit Reflexions-oder die Nachteile Ihrer Lösung.Typen T und []T, sind verschiedene Arten und verschiedene sind Ihre Methoden, auch wenn die Befriedigung der gleichen Schnittstelle. IOW, jede Art befriedigend Modell implementieren müssen alle sich das Modell der Methoden von selbst - die Methode receiver kann nur einen bestimmten Typ.
Als andere haben schon geantwortet, []T ist ein eigener Typ. Ich möchte nur hinzufügen, dass eine einfache Dienstprogramm kann verwendet werden, konvertieren Sie generisch.
Nun, Sie können es verwenden, wie diese:
Gehen, auch wenn die Umsetzung erlaubt dies, es ist leider ungesund: Sie können nicht zuordnen
[]Person
auf eine variable vom Typ[]Model
weil ein[]Model
hat unterschiedliche Fähigkeiten. Zum Beispiel, nehmen wir an, wir haben auchAnimal
implementiertModel
:Wenn wir zulassen, dass Zeile 2, dann Zeile 3 sollte auch funktionieren, da
models
können sehr gut speichernAnimal
. Und Zeile 4 sollte weiterhin funktionieren, dapeople
speichertPerson
s. Aber dann haben wir am Ende eine variable vom TypPerson
hält eineAnimal
!Java tatsächlich erlaubt die Entsprechung von Zeile 2, und es ist weithin als ein Fehler. (Der Fehler ist gefangen im Lauf der Zeit; die Linie 3 würde werfen ein
ArrayStoreException
.)