这个例子是我试图解决的更大问题的模型。顶部的层次结构是抽象特征CarFamily,然后从CarFamily延伸出3个抽象特征,即本田,思域和沃尔沃。我的目标是能够在从这3个特征扩展的实例中为每个子特征调用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)
因此,问题的根本原因是您的根特征中有一个抽象的val
。 val
按顺序初始化(并非一次性完成),此订单有时可能会令人惊讶 - 例如如果你覆盖这些null
或者从同一个班级的任何地方获得前向引用,你会看到val
你不期望它们的位置。
因此,避免此类问题的经验法则很简单:总是将def
用于抽象成员。
此规则增加了额外的好处,即在用于实现/覆盖这些字段的成员类型中具有灵活性:您可以使用def
,def
扩展val
,{ {1}}或var
(后者有时非常有用)。
此外,我试图了解您尝试使用此代码实现的目标,并且我认为您对Scala中的多重继承的理解可能是错误的。即使您在根特征中使用lazy val
,def
内也只会有carModel
和carModelStatement
的一个值 - 为依赖于的所有内容产生相同的字符串这个属性。
答案 1 :(得分: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
答案 2 :(得分:0)
我也遇到过类似的情况。使用this.
解决了这个问题。
trait CarFamily {
var carModel: String = "test" //assign some string and change val to var
def carModelStatement: String = s"The model of the car is ${carModel}"
}
trait Honda extends CarFamily {
this.carModel= "honda" //pass the actual string value
}