Imran
Imran

Reputation: 181

Scala typed trait different types Implementation keeping it in Map, not working

Is there any better design to achieve this scenario?

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())
  }
}

Here what I am trying to achieve is deferent implementation say CowPropertyImpl, DogPropertyImpl , or some more different implementations, I am keeping it in a Map and in runtime based on user input I am retrieving the implementation from Map and calling the method of that Impl class

Upvotes: 1

Views: 54

Answers (1)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149636

This is a good candidate for the 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
}

Based on the type of A (cat, dog) we get the desired properties of each animal.

Upvotes: 3

Related Questions