Scala类型特征不同类型实现将其保存在Map中,而不是工作

时间:2018-06-08 15:06:24

标签: scala scala-collections

有没有更好的设计来实现这种情况?

case class Animal()
case class Dog() extends Animal
case class Cow() extends Animal

trait BasePropertyImpl[T <: Animal] {
  def property1(animal: T): T

  def property2(animal: T): T
}

object DogPropertyImpl extends BasePropertyImpl[Dog] {
  def property1(animal: Dog): Dog = ???

  def property2(animal: Dog): Dog = ???
}

object CowPropertyImpl extends BasePropertyImpl[Cow] {
  def property1(animal: Cow): Cow = ???

  def property2(animal: Cow): Cow = ???
}

object AnimalImplRegistrar {
  def getRegisteredAnimals: Map[String, BasePropertyImpl[Animal]] = Map(
    "Dog" -> DogPropertyImpl,
    "Cow" -> CowPropertyImpl,
  )
}

object Main {
  def main(args: Array[String]): Unit = {
    val animal = AnimalImplRegistrar.getRegisteredAnimals.get("Dog").get
    aminal.property1(Dog())
  }
}

这里我想要实现的是不同的实现说CowPropertyImpl,DogPropertyImpl,或者更多不同的实现,我将它保存在Map中并在运行时基于用户输入我从Map检索实现并调用方法Impl class

1 个答案:

答案 0 :(得分:3)

这是Type Class Pattern的理想候选人:

sealed trait Animal
case object Dog extends Animal
case object Cat extends Animal

trait AnimalProperties[A] {
  def property: A
} 

object AnimalProperties {
  implicit val dogProperties = new AnimalProperties[Dog.type] {
    override def property: Dog.type = ???
  }

  implicit val catProperties = new AnimalProperties[Cat.type] {
    override def property: Cat.type = ???
  }
}

def f[A](a: A)(implicit ev: AnimalProperties[A]) = {
  val a: A = ev.property
}

根据A(猫,狗)的类型,我们可以获得每只动物所需的属性。