Reputation:
I need to do a pattern match on Classes. The Problem is, that I have some Problems matching a Long.
I need to handle scala.Long and java.lang.Long in the same way, but why do I need to declare them both in cases?
Here is an example:
def test(typ: Class[_]) {
typ match {
case q if q == classOf[Long] => println("scala long...")
}
}
val scalaLongField: java.reflect.Field = ......
val javaLongField: java.reflect.Field = ......
test(scalaLongField.getType) // prints "scala long..."
test(javaLongField.getType) // scala.MatchError: class java.lang.Long (of class java.lang.Class)
Is there a way to handle them the same without having an instance but just the class?
Upvotes: 5
Views: 4892
Reputation: 63399
The reason is that java.lang.Long
and Long
are different classes. In Java, there is a difference between java.lang.Long.class
and Long.TYPE
. Similarly, in Scala, classOf[Long]
and classOf[java.lang.Long]
are different.
If you want to pattern match on classes, you can create helper unapply
methods for that:
object ScalaLong {
// Internal helper:
private def matchClass[T](c: Class[_], as: Class[T]): Option[Class[T]] =
if (as.isAssignableFrom(c)) Some(as)
else None;
// Matches wrapped Long classes.
object LongObject {
def unapply(c: Class[_]): Option[Class[java.lang.Long]] =
matchClass(c, classOf[java.lang.Long]);
}
// Matches primitive long classes.
object LongPrim {
def unapply(c: Class[_]): Option[Class[Long]] =
matchClass(c, classOf[Long]);
}
// -- Test:
def check(clz: Class[_]) =
clz match {
case LongPrim(c) => println("Long primitive: " + c);
case LongObject(c) => println("Long object: " + c);
case _ => println("Other: " + clz);
}
class Example {
val l1: scala.Long = 1L;
val l2: java.lang.Long = 1L;
val l3: java.lang.Integer = 1;
}
def main(argv: Array[String]) {
for(name <- Seq("l1", "l2", "l3"))
check(classOf[Example].getMethod(name).getReturnType());
}
}
Generally, you'll have to treat classOf[Long]
and classOf[java.lang.Long]
separately. Perhaps, if you describe what you need to do with them, we can find a better solution for your specific task.
Upvotes: 4
Reputation: 67310
It should work straight away:
object LongTest {
def test(value: Any): Boolean = value match {
case l: Long => true
case _ => false
}
def run() {
println(test(1L))
println(test(new java.lang.Long(1L)))
}
}
LongTest.run() // true and true
It wasn't obvious to me that you want to match classes instead of instance. I'm not sure I understand what you actually want. Like this?
object LongTest {
def test(clazz: Class[_]): Boolean =
clazz == classOf[Long] || clazz == classOf[java.lang.Long]
def run() {
println(test(1L.getClass))
println(test(new java.lang.Long(1L).getClass))
}
}
LongTest.run() // true and true
Or as a pattern match:
def test(clazz: Class[_]): Boolean = clazz match {
case q if q == classOf[Long] || q == classOf[java.lang.Long] => true
case _ => false
}
Upvotes: 4