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

问题描述 投票:1回答:3

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

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
}

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

scala pattern-matching
3个回答
3
投票

每个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

2
投票

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

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


0
投票

如果这是在通用上下文中,您可以使用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 :(
© www.soinside.com 2019 - 2024. All rights reserved.