我们在第二篇文章里曾提到过:
本质上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类的设计目的来看,最重要的是提供构造器模式匹配(且构造时的参数,与解构的结果一致),另外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)
原创文章,作者:3628473679,如若转载,请注明出处:https://blog.ytso.com/140736.html