2017-12-21 19 views
0

私のコードベースでは、私はvarsから屈折する必要があります。コードベース構造は次の形式に従います。スカラ:valからvalへの再設計

class Animal { 
    var name : Option[String] = None 
    var owner : Option[String] = None 
} 

case class Dog(breed: String) extends Animal { 
    //Dog logic 
} 

この設計の主な理由は、情報がすべて同時に利用可能でないことです。

ので、JSONをデシリアライズservice Aから、私はAnimalAnimalDogのいずれか)

val animal = new Animal 
animal.name = "My little animal" 

、その後

def update(animal: Animal) : Unit { 
    animal match { 
     case a : Animal => a.owner = Some("Joe") // call to service B 
     case _   => //handle dog 
    } 
} 

update(animal) 

を受ける質問は:どのように私はそれを再設計することができますAnimalの可変状態を避ける?

  • Animalcopy方法を書きますか?複数のフィールドがあり、いくつかの定型文を生成する可能性があります。

  • 構成?

2クラスを作るcase

case class Animal (...) 
case class Dog(animal: Animal, breed: String) 

編集私はDogsAnimals(本当にAnimalとnoサブタイプを持つことになりますと、私はまだ、Animalの具体的な実装を必要とするtrait

として

  • アニマル)

    • コピー

    の問題の場合、クラスのコピーメソッドに建てられ、Animalクラスの値を更新しません。したがって、私が望むものではなく、デフォルト値が使用されます。 - はい、すべてのフィールドでケースクラスを作成することは可能ですが、100以上のフィールドがある場合は実用的ですか?

+1

ケースクラスには、コピーメソッドが含まれています。https://stackoverflow.com/questions/7249396/how-to-clone-a-case-class-instance-and-change-just-one-field-in-scala – ameer

答えて

0

あなたはこのようなADT(抽象データ型)としてこれを設計することができます:

trait Animal { 
    def name: Option[String] 
    def owner: Option[String] 
} 

case class Dog(dog: Option[String] = None, owner: Option[String] = None) extends Animal 

ケースクラスを使用すると、デフォルトでコピー方法を持っています!

+0

If 'Animal'はデシリアライゼーションが' Animal'を作成するのに失敗する 'trait'です – Bruno

+0

ドッグケースクラスにextends節を追加して編集しました – sparkr

0

良い解決策は、Animal動作を指定形質を作る

sealed trait Animal { 
    val name: Option[String] 
    val owner: Option[String] 
} 

、その後case class ESはあなたの動物インスタンスのタイプのコンストラクタを提供できるようにすることである可能性があります。

case class Dog(name: Option[String], owner: Option[String]) extends Animal 

さて、updatechangeOwner)はAnimalがかかりますし、同様に別のAnimalを返す:

def changeOwner(animal: Animal): Animal = animal match { 
    case Dog(name, owner) => Dog(name, Some("Joe")) 
    case _ => animal 
} 

を、次のようにあなたはそれを使用します。

val dog: Animal = Dog(Some("Doggie"), Some("Jack")) 
val newDog: Animal = changeOwner(dog) 

また、あなたのコードから:

case a : Animal => a.owner = Some("Joe") // call to service B 

matchの最初のcaseはすべての動物を服用するため、他のケース、たとえばDogの場合は手が届きません。

+0

' trait Animal'が私に合わない理由と 'copy'の欠点を説明しました。 – Bruno

関連する問題