Class 如何以编程方式确定该类是案例类还是简单类?

Class 如何以编程方式确定该类是案例类还是简单类?,class,scala,Class,Scala,如何以编程方式确定给定类是案例类还是简单类?目前(2011年),您可以使用反射来确定该类是否实现了接口scala.Product: scala> def isCaseClass(o: AnyRef) = o.getClass.getInterfaces.find(_ == classOf[scala.Product]) != None isCaseClass: (o: AnyRef)Boolean scala> isCaseClass(Some(1)) res3: Boolean

如何以编程方式确定给定类是案例类还是简单类?

目前(2011年),您可以使用反射来确定该类是否实现了接口
scala.Product

scala> def isCaseClass(o: AnyRef) = o.getClass.getInterfaces.find(_ == classOf[scala.Product]) != None
isCaseClass: (o: AnyRef)Boolean

scala> isCaseClass(Some(1))
res3: Boolean = true

scala> isCaseClass("")
res4: Boolean = false
这只是一个近似值-您可以进一步检查它是否有
copy
方法,是否实现了
Serializable
,是否有一个带有适当
apply
unapply
方法的伴生对象-本质上,使用反射检查case类所期望的所有内容

下一个版本中的scala反射包将使案例类检测更容易、更精确

编辑:


现在,您可以使用新的Scala反射库来实现这一点——请参阅其他答案。

如果您的意思是:我可以通过编程方式确定一个类是案例类还是非案例类,答案是否,但您可以进行近似。Case类只是一个编译器黑客,它们告诉编译器创建某些方法等。在最终的字节码中,普通类和Case类之间没有区别

  • 你可以在上面做模式匹配
  • 您可以构造这些类的实例,而无需使用新的 关键词
  • 所有构造函数参数都可以从外部使用 自动生成的访问器函数
  • toString方法会自动重新定义以打印名称 case类及其所有参数的
  • equals方法会自动重新定义以比较两个 同一案例类的实例在结构上而不是在标识上
  • hashCode方法会自动重新定义以使用 构造函数参数的哈希代码
  • 因此,您实际上可以通过自己定义正确的方法和伴随对象来创建case类


    要了解如何确定类是否可以成为案例类,请查看axel22的答案。

    使用新的Scala反射API:

    scala> class B(v: Int)
    defined class B
    
    scala> case class A(v: Int)
    defined class A
    
    scala> def isCaseClassOrWhat_?(v: Any): Boolean = {
         |   import reflect.runtime.universe._
         |   val typeMirror = runtimeMirror(v.getClass.getClassLoader)
         |   val instanceMirror = typeMirror.reflect(v)
         |   val symbol = instanceMirror.symbol
         |   symbol.isCaseClass
         | }
    isCaseClassOrWhat_$qmark: (v: Any)Boolean
    
    scala> class CaseClassWannabe extends Product with Serializable {
         |   def canEqual(that: Any): Boolean = ???
         |   def productArity: Int = ???
         |   def productElement(n: Int): Any = ???
         | }
    defined class CaseClassWannabe
    
    scala> isCaseClassOrWhat_?("abc")
    res0: Boolean = false
    
    scala> isCaseClassOrWhat_?(1)
    res1: Boolean = false
    
    scala> isCaseClassOrWhat_?(new B(123))
    res2: Boolean = false
    
    scala> isCaseClassOrWhat_?(A(321))
    res3: Boolean = true
    
    scala> isCaseClassOrWhat_?(new CaseClassWannabe)
    res4: Boolean = false
    

    谢谢你,阿克塞尔。这是我问题的解决办法。我希望开发人员尽快添加Scala的这种方法。Сlass实现接口scala.Product-这是它的一个充分条件?不,没有足够的条件来检查它(afaik)。您不能检查原始代码中是否存在
    case
    修饰符,只能检查由于
    case
    修饰符而生成的方法。正如我在上面写的,整个过程只是一个近似值。这太棒了。。但是您需要一个类的实例来检测这一点。仅使用类型信息就可以完成吗?毕竟,问题是检测
    类是否是case类而不是实例是否来自case类。您也可以对类进行反思,例如使用
    typeMirror.classSymbol(clazz).isCaseClass