Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use isInstanceOf and when to use a match-case-statement (in Scala)?

Tags:

match

scala

sealed class A
class B1 extends A    
class B2 extends A

Assuming we have a List of objects of class A : val l: List[A] = List(new B1, new B2, new B1, new B1)

And we want to filter out the elements of the type B1. Then we need a predicate and could use the following two alternatives:

l.filter(_.isInstanceOf[B1])

Or

l.filter(_ match {case b: B1 => true; case _ => false})

Personally, I like the first approach more, but I often read, one should use the match-case statement more often (for reasons I do not know).

Therefore, the question is: Are there drawbacks of using isInstanceOf instead of the match-case statement ? When should one use which approach (and which approach should be used here and why) ?

like image 432
John Threepwood Avatar asked Jun 27 '12 15:06

John Threepwood


People also ask

What is Scala match case?

Advertisements. Pattern matching is the second most widely used feature of Scala, after function values and closures. Scala provides great support for pattern matching, in processing the messages. A pattern match includes a sequence of alternatives, each starting with the keyword case.

What is match expression in Scala?

“match” is always defined in Scala's root class to make its availability to the all objects. This can contain a sequence of alternatives. Each alternative will start from case keyword. Each case statement includes a pattern and one or more expression which get evaluated if the specified pattern gets matched.

What is the default option in a match case in Scala?

getList("instance").

What is case class and pattern matching Scala?

Scala's pattern matching statement is most useful for matching on algebraic types expressed via case classes. Scala also allows the definition of patterns independently of case classes, using unapply methods in extractor objects.


4 Answers

You can filter like that:

l.collect{ case x: B1 => x }

That is much more readable, IMO.

like image 108
om-nom-nom Avatar answered Oct 01 '22 03:10

om-nom-nom


There's no problem using isInstanceOf, as long as you don't use asInstanceOf.

Code that uses both is brittle, because checking and casting are separate actions, whereas using matching you have a single action doing both.

like image 28
Daniel C. Sobral Avatar answered Oct 01 '22 01:10

Daniel C. Sobral


There are no difference

cat t.scala:

class A {
  def x(o: AnyRef) = o.isInstanceOf[A]
  def y(o: AnyRef) = o match {
    case s: A => true
    case _ => false
  }
}

$ scalac -print t.scala

[[syntax trees at end of cleanup]]// Scala source: t.scala
package <empty> {
  class A extends java.lang.Object with ScalaObject {
    def x(o: java.lang.Object): Boolean = o.$isInstanceOf[A]();
    def y(o: java.lang.Object): Boolean = {
      <synthetic> val temp1: java.lang.Object = o;
      temp1.$isInstanceOf[A]()
    };
    def this(): A = {
      A.super.this();
      ()
    }
  }
}
like image 43
Zang MingJie Avatar answered Oct 01 '22 01:10

Zang MingJie


The advantage of match-case is that you don't have to cast the object in case you want to perform operations on it that depend on its narrower type.

In the following snippet, using isInstanceOf seems to be fine since you don't perform such an operation:

if (obj.isInstanceOf[A]) println(obj)

However, if you do the following:

if (obj.isInstanceOf[A]) {
  val a = obj.asInstanceOf[A]
  println(a.someField) // someField is declared by A
}

then I'd be in favour of using match-case:

obj match {
  case a: A => println(a.someField)
  case _ =>
}

It is slightly annoying that you have to include the "otherwise"-case, but using collect (as hinted at by om-nom-nom) could help, at least if you work with collections inherit from Seq:

collectionOfObj.collect{ case a: A => a}.foreach(println(_.someField))
like image 22
Malte Schwerhoff Avatar answered Oct 01 '22 02:10

Malte Schwerhoff