I'm trying to use pattern matching to match classes that extend from a parent class, but also restrict the classes you can pass as a parameter using classType: Class[_ <: Animal]
. Here's an example:
class Animal
class Dog extends Animal
class Cat extends Animal
def returnAnimalSubtypeObject(classType: Class[_ <: Animal]): Animal = {
classType match {
case _: Dog => new Dog()
case _: Cat => new Cat()
}
}
returnNewClass(Class[Dog])
But this returns the following error message:
<console>:16: error: pattern type is incompatible with expected type;
found : Dog
required: Class[_$1] where type _$1 <: Animal
case _: Dog => new Dog()
I think I'm not understanding something fundamental here since I'm still a beginner. Could someone explain what's the best approach to solving this?
CodePudding user response:
The Class
object for Dog
is not a Dog
: it's a Class
.
With the proviso that there's almost certainly a better way to accomplish what you actually want to do, you could:
def returnAnimalSubtypeObject(clazz: Class[_ <: Animal]): Animal =
if (clazz == classOf[Dog]) new Dog()
else if (clazz == classOf[Cat]) new Cat()
else new Animal()
CodePudding user response:
It seems like you are trying to implement something like ADT(Abstract Data Type). I would prefer to use sealed trait
or sealed abstract class
since it's better in pattern matching.
see also: https://nrinaudo.github.io/scala-best-practices/definitions/adt.html
sealed trait Animal
case class Dog(name: String, bark: Boolean) extends Animal
case class Cat(name: String, mow: Boolean) extends Animal
object Animal {
def returnAnimalSubtypeObject(x: Animal): Animal = x match {
case d: Dog => d
case c: Cat => c
}
}
scala> Animal.returnAnimalSubtypeObject(Dog("a dog can bark", true))
val res2: Animal = Dog(a dog can bark,true)
scala> Animal.returnAnimalSubtypeObject(Cat("a cat can mow", true))
val res3: Animal = Cat(a cat can mow,true)
When we use sealed
keywork, the Scala compiler will check the pattern match is exhaustive or not.
// if we miss a type to match
def returnAnimalSubtypeObject(x: Animal): Animal = x match {
case d: Dog => d
}
// it will show warning.
match may not be exhaustive.
[warn] It would fail on the following input: Cat(_, _)
[warn] def returnAnimalSubtypeObject(x: Animal): Animal = x match {
[warn] ^
[warn] one warning found