如何在 Scala“匹配”语句中匹配类?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7157143/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:22:59  来源:igfitidea点击:

How can I match classes in a Scala "match" statement?

scala

提问by Tim

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 if ... else ...

如何使用“匹配”语句来识别类变量的值?以下是无效的,我找不到可接受的变体——除了 if ... else if ... else ...

val c: Class[_] = classOf[Int]
val what = c match { case classOf[Int] => "int!"; case classOf[Float] => "float!" }

The compiler complains: error: not found: type classOf

编译器抱怨: error: not found: type classOf

And of course, I can't use Class[Int]because that type information is erased:

当然,我无法使用,Class[Int]因为该类型信息已被删除:

c match { case Class[Int] => "int!"; case Class[Float] => "float!" }
error: type Class of type Class does not take type parameters.

I've also tried variants like Int.class, all to no avail. (And I don't really want to convert to strings: I feel it's important to have the compiler catch renamed/moved classes.)

我也尝试过类似的变体Int.class,但都无济于事。(而且我真的不想转换为字符串:我觉得让编译器捕获重命名/移动类很重要。)

Am I being dense, or have I stumbled into a Scala blind spot?

我是不是很密集,还是偶然发现了 Scala 盲点?

回答by Debilski

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, classOfshould not work directly in a case statement anyway. However, neither does an escaped

当然,作为小写标识符,classOf无论如何都不应该直接在 case 语句中工作。然而,也没有逃脱

case `classOf`[Int]

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

在这种情况下工作,因此您必须使用if-guard。

回答by Miles Sabin

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

如果您为它们创建稳定的标识符(即 val),则可以匹配类值,

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

请注意,您不能匹配类型(即 Class[Int]),因为擦除意味着 Class[T] 的不同类型实例化在运行时无法区分……因此下面的警告

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!

回答by Peter L

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.

我遇到了同样的问题,将类放在“稳定标识符”中不太实用。我发现下一个最好的事情是拥有整洁的“else if”语句。

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)

回答by raisercostin

To consider inheritance:

考虑继承:

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