2017-07-11 4 views
0

この例は、私が解決しようとしているより大きな問題のモックアップです。一番上の階層は抽象的な特性CarFamilyであり、CarFamily、すなわちHonda、Civic、Volvoから3つの抽象的な特性が拡張されています。私の目標は、これらの3つの特性から拡張されたインスタンス内の各子特性のcarModelStatementを呼び出すことです。スカラ特性:子に値を渡して抽象親特性値を取得できません。

しかし、結果がわかるように、すべてのステートメントは「車のモデルはnullです」と返します。だから、val volvo、honda、市民は私が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を使用します。

このルールは、これらのフィールドをオーバーライド/実装するために使用する部材の種類に柔軟であるという付加的な利点を追加します。あなたが(後者は時間に非常に有用である)defvalvar又はlazy valdefを拡張することができ。

また、このコードで達成しようとしていることを理解しようとしましたが、Scalaの多重継承の理解が間違っていると考えています。あなたの根性にdefを使用しても、allModelsの中にそれぞれcarModelcarModelStatementという値が1つあります - このプロパティに依存するすべての文字列が同じになります。

+1

この経験則は一般的な誤解です。抽象的な 'val'を' def'に変更しても効果はありません。実装は 'val'か' sub'クラスの '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 
関連する問題