Zurück zu einer spezielleren Oberfläche

74

Ich schreibe ein Spiel in go. In C ++ würde ich alle meine Entitätsklassen in einem Array der BaseEntity-Klasse speichern. Wenn sich eine Entität in der Welt bewegen müsste, wäre dies eine PhysEntity, die von einer BaseEntity abgeleitet ist, jedoch zusätzliche Methoden enthält. Ich habe versucht, dies nachzuahmen.

package main

type Entity interface {
    a() string
}

type PhysEntity interface {
    Entity
    b() string
}

type BaseEntity struct { }
func (e *BaseEntity) a() string { return "Hello " }

type BasePhysEntity struct { BaseEntity }
func (e *BasePhysEntity) b() string { return " World!" }

func main() {
    physEnt := PhysEntity(new(BasePhysEntity))
    entity := Entity(physEnt)
    print(entity.a())
    original := PhysEntity(entity)
// ERROR on line above: cannot convert physEnt (type PhysEntity) to type Entity:
    println(original.b())
}

Dies wird nicht kompiliert, da es nicht sagen kann, dass 'Entität' eine PhysEntity war. Was ist eine geeignete Alternative zu dieser Methode?


quelle

Antworten:

119

Verwenden Sie eine Typzusicherung . Zum Beispiel,

original, ok := entity.(PhysEntity)
if ok {
    println(original.b())
}
peterSO
quelle
3
Wissen Sie, ob die Verwendung von Typzusicherungen teuer ist? Lohnt es sich, den Typ mit einer Variablen in der BaseEntity zu verfolgen?
6
Typ Behauptungen sind billig.
Rog
Wenn ich dies versuche, erhalte ich eine Fehlermeldung:invalid type assertion .. (non-interface type .. on left)
Zac
1
@Zac Da "type assertion" für "interface" gültig ist, ist Ihr Wert nicht "interface".
Khue Bui
7

Insbesondere enthält der Go-Typ "interface" die Informationen darüber, was das Objekt wirklich war, das von der Schnittstelle übergeben wurde. Daher ist das Casting viel billiger als ein C ++ dynamic_cast oder der entsprechende Java-Test-and-Cast.

Weregamer
quelle