2011-09-23 36 views

回答

2

目前(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,如果它具有與適當的applyunapply方法伴侶對象 - 在本質上,檢查所有來自使用反射的情況下,預期類的東西。

下一個版本中的scala反射包應該使case類檢測更容易和更精確。

編輯:

可以現在使用新的Scala庫的思考了 - 看其他答案。

+0

謝謝你,axel22。這是我的問題的解決方案。我希望開發人員儘快添加這種Scala方法。 Сlass實現接口scala.Product - 這是一個充分的條件嗎? – DimParf

+0

不,沒有足夠的條件來檢查這個(afaik)。您無法檢查原始代碼中是否存在「case」修飾符,僅限於由「case」修飾符生成的方法。正如我上面寫的,整個事情只是一個近似值。 – axel22

2

如果您的意思是:我可以通過編程確定類是案例類還是非案例類,答案是否定的,但您可以進行近似處理。案例類只是一個編譯器黑客,他們告訴編譯器創建某些方法等。在最終的字節碼中,普通類和案例類沒有區別。

How does a case class differ from a normal class?

  1. 你可以做模式上的匹配,
  2. 可以構造這些類的實例,而無需使用新的 關鍵字,
  3. 所有構造函數的參數是從外部利用訪問 自動生成的存取函數,
  4. toString方法被自動重新定義爲打印名稱 案例分類及其所有參數
  5. equals方法會自動重新定義,以在結構上而不是按身份比較兩個相同案例類的 實例。
  6. hashCode方法被自動重新定義爲使用的構造器參數的 散列碼。

所以,你可以通過只定義了正確的方法&同伴對象自己真正創建一個案例類。

有關如何找出類可能是案例類的想法,請查看axel22的答案。

16

使用新斯卡拉反射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 
相關問題