話說模式匹配(6) case類的細節

杜老師說 2022-01-07 13:19:52 阅读数:334

模式 匹配 case

我們在第二篇文章裏曾提到過:

本質上case class是個語法糖,對你的類構造參數增加了getter訪問,還有toString, hashCode, equals 等方法; 最重要的是幫你實現了一個伴生對象,這個伴生對象裏定義了apply方法和unapply方法。

現在我們來詳細的分析一下case class,對一個簡單的樣本類

case class B()

反編譯後看到編譯器自動給它混入了Product特質,以及Serializable特質:

public class B implements scala.Product,scala.Serializable { public B copy(); public java.lang.String productPrefix(); public int productArity(); public java.lang.Object productElement(int); public scala.collection.Iterator<java.lang.Object> productIterator(); public boolean canEqual(java.lang.Object); public int hashCode(); public java.lang.String toString(); public boolean equals(java.lang.Object); public B();}

再看看它的半生對象:

//伴生對象也混入了AbstractFunction0 和 Serializable 特質public final class B$ extends scala.runtime.AbstractFunction0<B> implements scala.Serializable { public static final B$ MODULE$; public static {}; public final java.lang.String toString(); public B apply(); public boolean unapply(B); public java.lang.Object apply();}

通過反編譯的結果我們了解到了幾點:

  1. 編譯器對case類混入了Product特質
  2. 編譯器對case類增加了copy方法;
  3. 編譯器對case類實現了equals/hashCode/toString等方法
  4. 伴生對象中最重要的方法是 unapply 這個方法是在進行構造器模式匹配時的關鍵。
  5. 伴生對象中apply方法則為創建對象提供方便,相當於工廠方法。
  6. 伴生對象繼承了AbstractFunction

從case類的設計目的來看,最重要的是提供構造器模式匹配(且構造時的參數,與解構的結果一致),另外case類可看作是數據對象,不可變的數據對象。

因為case類封裝的數據有不變的特點,以及可以進行模式匹配,所以它在actor中經常使用,很適合封裝消息在actor之間傳遞。

上面列出的幾點中,對於第6點“伴生對象繼承自 Function”可能感到奇怪,Martin在這裏回答了為什麼case類的伴生對象會繼承FunctionN

The reason why case class companion objects implement FunctionN is that before, case classes generated a class and a factory method, not a companion object. When we added extractors to Scala it made more sense to turn the factory method into a full companion object with apply and unapply methods. But then, since the factory method did conform to FunctionN, the companion object needed to conform, too.

另外,當參數大於2個時,FunctionN 都提供了tupled方法生成一個函數,該函數可以接受一個tuple作為參數構造出結果,比如:

scala> case class A(x: Int, y:Int)scala> A.tupledres11: ((Int, Int)) => A = <function1>scala> val t = (100,100)t: (Int, Int) = (100,100)scala> A.tupled(t)res9: A = A(100,100)

原創文章,轉載請注明: 轉載自並發編程網 – ifeve.com本文鏈接地址: 話說模式匹配(6) case類的細節

FavoriteLoading添加本文到我的收藏
版权声明:本文为[杜老師說]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/01/202201071319518469.html