noncom
noncom

Reputation: 4992

Scala - finding sequence members that are of a certain type's child type

I have the following situation:

Java lib class:

class LibClass {
  ArrayList<LibClass> children;
}

my program Scala code:

abstract class MyClass extends LibClass {
  def boom { }
  def boomMyClassInstances  // ???
}

class Lala extends MyClass
class Hoho extends MyClass

The question is: in the method boomMyClassInstances what is the most Scala-ish way to get all the children of MyClass, stored in the children ArrayList so that I can call the common boom method upon them all?

My try is:

def boomMyClassInstances {
  children.toArray.map { case mc: MyClass => mc.boom }
}

Is this a correct approach? Will it pick all the children of MyClass and this is the right Scala way for that, or do I have to say something about type bounds?

Upvotes: 1

Views: 319

Answers (4)

oxbow_lakes
oxbow_lakes

Reputation: 134260

You want to collect the relevant portion:

children.iterator collect { case mc: MyClass => mc } foreach (_.boom())

Upvotes: 1

Donald.McLean
Donald.McLean

Reputation: 889

I'm not a type expert, so I can't say definitively that your solution will work, however it does seem that it should work. It has the advantage of being straightforward, which is always good.

You do need to add a catch-all case though (so as to not get a scala.MatchError).

case _ => // do nothing

Upvotes: 2

missingfaktor
missingfaktor

Reputation: 92016

import collection.JavaConverters._

children.asScala.foreach { 
  case mc: MyClass => mc.boom 
  case _ => ()
}

Upvotes: 5

Malte Schwerhoff
Malte Schwerhoff

Reputation: 12852

Check out GenTraversableLike.collect. Its signature essentially is Traversable[A].collect[B <: A](f: A ~> B): Traversable[B], that is, it takes a collection with elements of type A and a partial function f from A to B, and returns a collection of static element-type B, where B is a subtype of A.

val myClassInstances: List[MyClass] =
  children.toList.collect{case mc: MyClass => mc}

Since map expects a total function, your try above will fail with an scala.MatchError in case children does not only contain instances of MyClass. You can work around this by using Option or flatMap, but collect seems to be the most Scala-ish way of achieving what you want.

Upvotes: 4

Related Questions