简体   繁体   中英

Scala: How to pattern match scala.Long and java.lang.Long

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?

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
  }

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM