0

Possible Duplicate:
How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections?

I ran the following code:

scala>  var s = new Stack()push(1)
s: scalatest.Stack[Int] = 1 

scala>  s match { case s : Stack[String] => print("Hello")}
<console>:12: warning: non variable type-argument String in type pattern scalatest.Stack[String] is unchecked since it is eliminated by erasure
              s match { case s : Stack[String] => print("Hello")
}

Stack is the class taken from http://www.scala-lang.org/node/129. If I run this code without -unchecked flag it will print "Hello". Why is that the case?

Community
  • 1
  • 1
Bober02
  • 15,034
  • 31
  • 92
  • 178

1 Answers1

2

The problem is that you're matching s to be of type Stack[String]. During runtime, it's possible to determine if s is of type Stack, but because of Java's type erasure it's not possible to determine if s is of type Stack[String], Stack[Int] etc. So no matter what the type parameter was, it gets matched by the case expression. This is why Scala issues the warning. It is the same as if you match as

s match { case s : Stack[_] => print("Hello")}

(which will compile without warnings).


Edit: A workaround (for Java too) is to create a specific class that doesn't have type parameters any more. For example:

import scala.collection.mutable.Stack;

object Test extends App {
  class MyStack extends Stack[Int];
  class MyOtherStack extends Stack[String];

  val s: Stack[_] = new MyStack().push(1);

  s match {
    case s : MyOtherStack => print("Hello String");
    case s : MyStack => print("Hello Int");
  }
}

It has a drawback that you cannot use it for immutable containers, because their methods create new objects and they won't be instances of these our specific subclasses.

Petr
  • 62,528
  • 13
  • 153
  • 317