Freewind
Freewind

Reputation: 198178

Define a method to filter items from list by Type

I'm trying to filter a list by the type of items. The working code is here:

trait Action

class AAA extends Action
class BBB extends Action

val list = List(new AAA, new BBB, new AAA)

def find[T <: Action] = list.filter(_.isInstanceOf[T])

find[AAA]

It doesn't work as expected, see the output:

scala> def find[T <: Action] = list.filter(_.isInstanceOf[T])
<console>:11: warning: abstract type T is unchecked since it is eliminated by erasure
       def find[T <: Action] = list.filter(_.isInstanceOf[T])
                                                     ^
find: [T <: Action]=> List[Action]

scala> find[AAA]
res0: List[Action] = List(AAA@2b9cbeec, BBB@3fba8e52, AAA@70d5ca2d)

How to fix it?

Upvotes: 1

Views: 205

Answers (2)

user2563536
user2563536

Reputation: 1

use implicit m:scala.reflect.Manifest[T]

def find[T <: Action](implicit m:scala.reflect.Manifest[T]) = 
     list.filter{x:Any => m.erasure.isInstance(x)}.asInstanceOf[List[T]]

Upvotes: 0

senia
senia

Reputation: 38045

You could use ClassTag:

def find[T <: Action : ClassTag] =
  list.filter{ implicitly[ClassTag[T]].runtimeClass.isInstance }

scala> find[AAA]
res0: List[Action] = List(AAA@145332ca, AAA@135cfef8)

It would be better to use collect method:

list.collect{ case e: AAA => e }

Upvotes: 2

Related Questions