How can I match classes in a Scala “match” statement?

前端 未结 4 1883
孤独总比滥情好
孤独总比滥情好 2021-01-01 14:43

How can I use a \"match\" statement to identify the value of a class variable? The following is invalid, and I can\'t find an acceptable variant -- other than if ... else i

相关标签:
4条回答
  • 2021-01-01 14:54

    I encountered the same problem and placing the class in a 'stable identifier' wasn't that practical. I found the next best thing was to have tidy 'else if' statements.

    Using this method:

    private def is[T <: AnyRef : Manifest](implicit cls: Class[_]) = 
        cls == manifest[T].runtimeClass
    

    I can write:

      implicit val arg = cls   
      if (is[ClassA]) ...
      else if (is[ClassB]) ...
      ...
      else throw new IllegalArgumentException("Unknown class: " + cls)
    
    0 讨论(0)
  • 2021-01-01 14:54

    To consider inheritance:

    val what = c match {
      case q if classOf[Int].isAssignableFrom(q) => "int!"
      case q if classOf[Float].isAssignableFrom(q)  => "float!"
    }
    
    0 讨论(0)
  • 2021-01-01 15:01

    The verbose case comparison works:

    val what = c match {
      case q if q == classOf[Int] => "int!"
      case q if q == classOf[Float] => "float!"
    }
    

    Of course, being a lower-case identifier, classOf should not work directly in a case statement anyway. However, neither does an escaped

    case `classOf`[Int]
    

    work in this case, so you’ll have to go with the if-guard.

    0 讨论(0)
  • 2021-01-01 15:15

    You can match on class values if you create a stable identifier (ie. a val) for them,

    scala> val c: Class[_] = classOf[Int]
    c: Class[_] = int
    
    scala> val ClassOfInt = classOf[Int]
    ClassOfInt: java.lang.Class[Int] = int
    
    scala> val ClassOfFloat = classOf[Float]
    ClassOfFloat: java.lang.Class[Float] = float
    
    scala> val what = c match {
         |     case ClassOfInt => "int!"
         |     case ClassOfFloat => "float!"
         | }
    what: String = int!
    

    Note that you can't match on type (ie. Class[Int]) because erasure means that the different type instantiations of Class[T] are indistinguishable at runtime ... hence the warning below

    scala> val what = c match {
         |     case _: Class[Int] => "int!"
         |     case _: Class[Float] => "float!"
         | }
    warning: there were 2 unchecked warnings; re-run with -unchecked for details
    what: java.lang.String = int!
    
    0 讨论(0)
提交回复
热议问题