Reputation: 181
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
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