2017-07-11 44 views
0

这个例子是一个我试图解决的更大问题的模型。顶部的层次结构是抽象特征CarFamily,然后有3个从CarFamily延伸出来的抽象特征,即本田,思域和沃尔沃。我的目标是能够从这三个特征延伸出来的实例中为每个子特征调用carModelStatement。斯卡拉特质:通过在孩子中传递值不能获取抽象的父特征值

但是,正如您可以看到结果一样,这些语句都返回“汽车模型为空”。所以val volvo,honda,civic没有被传递给我是Scala的新手。想知道我错过了什么,或者如果有另一种设计来获得我想要的。谢谢!

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

我怕,当你得到这个工作,你会发现,它并没有完全做到,你可能期待什么。 –

回答

0

所以问题的根本原因是你的根特征中有一个抽象的valval按顺序初始化(并非全部一次),并且这个顺序有时可能令人惊讶 - 例如,你会看到null s,如果你忽略这些val s,或者在同一个类的任何地方有前向参考,你不会期望它们。

所以避免这种问题的经验法则很简单:总是使用def作为抽象成员

此规则添加的是在成员的类型灵活地使用以实现/覆盖这些领域一个额外的好处:可以与延伸def一个defvalvarlazy val(有时后者是非常有用的) 。此外,我试图掌握你试图用这段代码实现的目标,我想你对Scala中多重继承的理解可能是错误的。即使在根特征中使用def,在allModels中分别只有一个值carModelcarModelStatement - 对于取决于此属性的所有内容都会产生相同的字符串。

+1

这个经验法则是一个常见的误解。将抽象的'val'改为'def'不会产生任何影响,重要的是实现是val还是取决于子类的val。 –

0

我不认为你可以以你想要的方式'存储'特质成员的价值。

这工作虽然:

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 

输出:

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