2017-07-11 4 views
0

Dieses Beispiel ist ein Modell eines größeren Problems, das ich versuche zu lösen. Die Hierarchie an der Spitze ist die abstrakte Eigenschaft CarFamily, dann gibt es 3 abstrakte Merkmale erstreckt sich von CarFamily, nämlich Honda, Civic und Volvo. Mein Ziel ist es, das carModelStatement für jedes Kind-Merkmal in einer Instanz aufrufen zu können, die sich von diesen 3 Merkmalen erstreckt.Scala-Eigenschaft: Kann abstrakte Elternattributwerte nicht erhalten, indem Werte im Kind übergeben werden

Wie Sie jedoch die Ergebnisse sehen, die Aussagen alle zurück "Das Modell des Autos ist Null". Also wurde der Valvolvo, Honda, Civic nicht an das Ich bin neu in Scala übergeben. Möchte wissen, was ich vermisse oder ob es ein anderes Design gibt, um zu bekommen, was ich will. Vielen Dank!

trait CarFamily { 
val carModel: String 
def carModelStatement: String = s"The model of the car is ${carModel}" 
} 

trait Honda extends CarFamily { 
val honda: String 
override val carModel: String = honda 
def hondaModelStatement : String = carModelStatement 
} 

trait Civic extends CarFamily { 
val civic: String 
override val carModel: String = civic 
def civicModelStatement : String = carModelStatement 
} 

trait Volvo extends CarFamily { 
val volvo: String 
override val carModel: String = volvo 
def volvoModelStatement : String = carModelStatement 
} 

object allModels extends Volvo with Civic with Honda { 
val volvo = "Volvo X3" 
val civic = "Civic Family" 
val honda = "Honda Extreme" 

} 

allModels.volvoModelStatement //res1: String = The model of the car is null 
allModels.civicModelStatement // res2: String = The model of the car is null 
allModels.hondaModelStatement // res3: String = The model of the car is null 
+0

Ich habe Angst, dass, wenn Sie diese, an die Arbeit Sie werden feststellen, dass es nicht recht tun, was Sie vielleicht erwarten . –

Antwort

0

So ist die Ursache des Problems, dass Sie eine abstrakte val in Ihrem Stammmerkmal haben. val s werden in der Reihenfolge initialisiert (nicht alle auf einmal), und diese Reihenfolge kann manchmal überraschend sein - z. Sie werden null s sehen, wo Sie sie nicht erwarten würden, wenn Sie diese val s überschreiben oder eine Vorwärtsreferenz von irgendwo in derselben Klasse haben.

Die Faustregel, solche Probleme zu vermeiden, ist einfach: verwenden Sie immer def für abstrakte Mitglieder.

Diese Regel fügt einen zusätzlichen Vorteil in der Art des Mitglieds flexibel diese Felder zu verwenden, zu implementieren/außer Kraft setzen: Sie def erweitern können def mit a, val, var oder lazy val (letzteres manchmal sehr nützlich sein) .

Außerdem habe ich versucht zu begreifen, was Sie mit diesem Code erreichen wollen und ich denke, dass Ihr Verständnis der Mehrfachvererbung in Scala wahrscheinlich falsch ist. Selbst wenn Sie def in Ihrem Stammmerkmal verwenden, gibt es nur einen Wert von und carModelStatement innerhalb allModels - identische Zeichenfolgen für alles, was von dieser Eigenschaft abhängt.

+1

Diese Faustregel ist ein häufiges Missverständnis. Das Ändern des abstrakten "val" in "def" hat keinen Effekt, was wichtig ist, ist die Implementierung ein "val" oder abhängig von "val's der Unterklasse. –

0

Ich glaube nicht, dass Sie den Wert in einem Merkmalelement auf die Weise "speichern" können, wie Sie es versuchen.

Das funktioniert aber:

trait CarFamily { 
    def carModelStatement(carModel: String): String = s"The model of the car is ${carModel}" 
} 

trait Honda extends CarFamily { 
    val honda: String 
    def hondaModelStatement : String = carModelStatement("honda") 
} 

trait Civic extends CarFamily { 
    val civic: String 
    def civicModelStatement : String = carModelStatement("civic") 
} 

trait Volvo extends CarFamily { 
    val volvo: String 
    def volvoModelStatement : String = carModelStatement("volvo") 
} 

object allModels extends Volvo with Civic with Honda { 
    val volvo = "Volvo X3" 
    val civic = "Civic Family" 
    val honda = "Honda Extreme" 

} 

allModels.volvoModelStatement 
allModels.civicModelStatement 
allModels.hondaModelStatement 

Ausgang:

res0: String = The model of the car is volvo 
res1: String = The model of the car is civic 
res2: String = The model of the car is honda 
Verwandte Themen