How to tell if a Scala reified type extends a cert

2019-08-13 00:48发布

问题:

In Scala, I am grabbing the type of a given class through its Scala manifest and storing it. My question is, how can I then check that type to see if the original class is descended from one parent class or another?

It looks like I can't perform a pattern match on t: Class[MyParentClass] because of type erasure, as below:

trait Product
trait PerishableProduct extends Product

class Fridge extends Product
class Banana extends PerishableProduct

def getProductType[P <: Product](implicit manifestP: Manifest[P]): Class[P] =
  manifestP.erasure.asInstanceOf[Class[P]]

val isPerishable = getProductType[Fridge] match {
  case x: Class[PerishableProduct] => true
  case _ => false
}
// ^^ warning: non variable type-argument PerishableProduct in type pattern
// Class[PerishableProduct] is unchecked since it is eliminated by erasure

Is there another trick I'm missing?

回答1:

How about good old reflection:

def isPerishable[P](implicit m: Manifest[P]): Boolean = 
  classOf[PerishableProduct].isAssignableFrom(m.erasure)

isPerishable[Fridge]   // false
isPerishable[Banana]   // true


回答2:

The problem is that you need manifest when you are dealing with type erasure. Manifest provides an easy way to perform this test with <:<.

println( manifest[Fridge] <:< manifest[PerishableProduct] )
println( manifest[Banana] <:< manifest[PerishableProduct] )

The above have direct type references so to update getProductType for however it will be used.

def getProductType[P <: Product](implicit manifestP: Manifest[P]): Manifest[P] = manifestP
val isPerishable = getProductType[Fridge] <:< manifest[PerishableProduct]
println( isPerishable )


标签: scala types