Reputation: 282
My application handles a lot of third party integrations. I have an abstract base class for third party integrations which specifies a bunch of methods that an integration class should handle – then certain integrations can be extended with additional functionality that is not available on all integrations.
Basically it looks like this:
abstract class Integration { ... }
trait SingleSignOn { ... }
class NormalIntegration extends Integration {}
class SingleSignOnIntegration extends Integration with SingleSignOn {}
I would like to be able to sort out all integrations that have a specific trait, and this is what I thought of as the basic solution:
val allIntegrations: Seq[Integration] = ...
def integrationsWithTrait[T]: Seq[Integration] = {
allIntegrations.filter(_.isInstanceOf[T])
}
The usage is:
val singleSignOnIntegrations = integrationsWithTrait[SingleSignOn]
The issue is that isInstanceOf[T]
always returns true (meaning I end up with singleSignOnIntegrations == allIntegrations
), while hard coded isInstanceOf[SingleSignOn]
works as intended.
How do I fix integrationsWithTrait
to work as I intend?
Upvotes: 4
Views: 1364
Reputation: 8673
This will work:
def integrationsWithTrait[T](implicit tag: scala.reflect.ClassTag[T]): Seq[Integration] = {
allIntegrations.filter(tag.runtimeClass.isInstance)
}
Scalac will inject ClassTag
instance for every class that this method will be called with. This will allow to access the Class
object in runtime and verify if the class is the instance of given class/trait.
I think the original code doesn't work because of type erasure.
Upvotes: 6