Scala - 模式匹配 - 是否可以检测值是否为案例类?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala - 模式匹配 - 是否可以检测值是否为案例类?相关的知识,希望对你有一定的参考价值。

我使用模式匹配来发现我的属性的类型,如下所示:

value match {
    case s: String => processString(s)
    case l: Long => processLong(l)
    case c1: myCaseClass1 => processCaseClass(c1)
    case c2: myCaseClass2 => processCaseClass(c2)
    case c3: myCaseClass3 => processCaseClass(c3)
    case _ => nothingToDo
}

是否可以检测值是否为案例类而不枚举我的所有案例类?

答案

每个case类和元组都默认扩展Product trait。因此,您可以使用Product捕获案例类和元组。警告:如果正常扩展Product特征,这可能会将普通类视为案例类。

value match {
  case _: Product => //catches all the case class values with tuple values also.
}

如果你想只捕获案例类

value match {
  case x: Product if !x.getClass.getName.startsWith("scala.Tuple") =>
    //catches all the case classes.
}

Scala REPL

scala> case class Dog(name: String)
defined class Dog

scala> case class Cat()
defined class Cat

scala> val value = Dog("foo")
value: Dog = Dog(foo)

scala> value match { case _: Product => println("caught") }
caught

scala> val value = Cat()
value: Cat = Cat()

scala> value match { case _: Product => println("caught") }
caught
另一答案

不,这是不可能的。案例类只包含一些编译器生成的成员,并且具有编译器生成的伴随对象,但是无论如何都可以手动实现。无法区分案例类和实现相同成员的非案例类。 The Scala Language Specification甚至包括编译器生成成员的确切扩展。

您可以手动编写一个类似于案例类的类,并且无法区分它们。

另一答案

如果这是在通用上下文中,您可以使用TypeTag获取有关传入的值类型的更多信息:

scala> :pa
// Entering paste mode (ctrl-D to finish)

import scala.reflect.runtime.universe.{TypeTag, symbolOf}

def foo[T: TypeTag](foo: T) =
  if (symbolOf[T].isClass && symbolOf[T].asClass.isCaseClass)
    println("It's a case class!")
  else
    println("Nope :(")

// Exiting paste mode, now interpreting.


scala> case class Foo(a: Int)
defined class Foo

scala> foo(Foo(3))
It's a case class!

scala> foo("bar")
Nope :(

以上是关于Scala - 模式匹配 - 是否可以检测值是否为案例类?的主要内容,如果未能解决你的问题,请参考以下文章

在 Scala 的模式匹配系统中使用比较运算符

模式匹配开销?

模式匹配`@`符号

Scala 的模式匹配是不是违反了开闭原则?

jQuery如何检测某个元素是否存在

可以在Scala中匹配范围吗?