我们在第二篇文章里曾提到过:
本质上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();
}
通过反编译的结果我们了解到了几点:
- 编译器对case类混入了
Product
特质 - 编译器对case类增加了
copy
方法; - 编译器对case类实现了
equals/hashCode/toString
等方法 - 伴生对象中最重要的方法是 unapply 这个方法是在进行构造器模式匹配时的关键。
- 伴生对象中
apply
方法则为创建对象提供方便,相当于工厂方法。 - 伴生对象继承了
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.tupled
res11: ((Int, Int)) => A = <function1>
scala> val t = (100,100)
t: (Int, Int) = (100,100)
scala> A.tupled(t)
res9: A = A(100,100)