首页 > 代码库 > 探索Scala(4)-- Case Classes
探索Scala(4)-- Case Classes
本文简单探讨一下Scala语言Case Class的实现机制
Case Class
Case Class是Scala语言模式匹配功能的基础。如果定义类的时候加上case关键字,那么它就变成了Case Class,比如下面这个简单的类CC:
case class CC(x: Int, y: Int)那么加上case关键字对于一个类来说,到底意味着什么呢?下文将进行详细的解释。
单例对象
编译CC,会产生两个class:CC.class和CC$.class。这说明,Scala会给case类自动添加一个单例对象。下面是反编译CC$.class之后的(部分)代码:
public final class CC$ extends scala.runtime.AbstractFunction2 implements scala.Serializable { public static final CC$ MODULE$; static { new CC$(); } private CC$() { MODULE$ = this; } public Object readResolve() { return MODULE$; } ... }
apply()和unapply()方法
CC$定义了apply()方法,这样我们就可以不用敲new关键字,而是通过下面这样的方式来创建CC实例:
val cc = CC(2, 16)CC$还定义了一个和apply()互补的方法:unapply(),它把CC拆成一个Option<Tuple>。apply()和unapply()方法的代码如下所示:
public final class CC$ ... { ... public CC apply(int x, int y) { return new CC(x, y); } public scala.Option<scala.Tuple2<Object, Object>> unapply(CC cc) { if (cc == null) { return scala.None$.MODULE$; } return new scala.Some(new scala.Tuple2$mcll$sp(cc.x, cc.y)) } }
Case Class默认是Immutable
Case类的字段,默认会被编译器加上val关键字,也就是说,CC类实际上是下面这样:
case class CC(val x: Int, val y: Int)下面是CC.class反编译之后的相应代码:
public class CC implements scala.Product, scala.Serializable { private final int x; private final int y; public CC(int x, int y) { this.x = x; this.y = y; scala.Product$class.$init$(this); } public int x() { return x; } public int y() { return y; } }
toString()、hashCode()和equals()方法
Scala编译器负责(根据字段)给Case类重写toString()、hashCode()和equals()方法。
copy()方法
copy()方法让Case类实例可以完整的,或者有少量变化的复制自己。如下面的代码所示:
val cc = CC(1, 2) val cc1 = cc.copy() val cc2 = cc.copy(y = 8) // Named arguments上面的代码去掉语法糖之后,实际上是下面这样:
val cc = CC(1, 2) val cc1 = cc.copy(cc.copy$default$1(), cc.copy$default$2()) val cc2 = cc.copy(cc.copy$default$1(), 8)下面是反编译之后copy()和copy$default$n()方法代码:
public class CC ... { ... public CC copy(int x, int y) { return new CC(x, y); } public int copy$default$1() { return x(); } public int copy$default$2() { return y(); } ... }
实现Product和Serializable接口
Case类还实现了scala.Product和scala.Serializable接口(Product和Serializable实际上都是Traits)。
完整的反编译代码
下面是CC.class和CC$.class的完整代码,仅供参考:
public class CC implements scala.Product, scala.Serializable { private final int x; private final int y; public CC(int x, int y) { this.x = x; this.y = y; scala.Product$class.$init$(this); } public int x() { return x; } public int y() { return y; } public int hashCode() {...} public boolean equals(Object) {...} public String toString() {...} public boolean canEqual(Object obj) { return obj instanceof CC; } public CC copy(int x, int y) { return new CC(x, y); } public int copy$default$1() { return x(); } public int copy$default$2() { return y(); } // Product // def productArity: Int // def productElement(n: Int): Any // def productIterator: Iterator[Any] // def productPrefix = "" public int productArity() { return 2; } public Object productElement(int n) { switch (n) { case 0: return x(); case 1: return y(); default: throw new IndexOutOfBoundsException(); } } public scala.collection.Iterator productIterator() { return scala.runtime.ScalaRunTime$.MODULE$.typedProductIterator(this); } public String productPrefix() { return "CC"; } public static CC apply(int x, int y) { return CC$.MODULE$.apply(x, y); } public static scals.Option<scala.Tuple2<Object, Object>> unapply(CC cc) { return CC$.MODULE$.unapply(cc); } public scala.Function1 static tupled() { return CC$.MODULE$.tupled(); } public scala.Function1 static curried() { return CC$.MODULE$.curried(); } }
public final class CC$ extends scala.runtime.AbstractFunction2 implements scala.Serializable { public static final CC$ MODULE$; static { new CC$(); } private CC$() { MODULE$ = this; } public Object readResolve() { return MODULE$; } public String toString() { return "CC"; } public CC apply(int x, int y) { return new CC(x, y); } public scala.Option<scala.Tuple2<Object, Object>> unapply(CC cc) { if (cc == null) { return scala.None$.MODULE$; } return new scala.Some(new scala.Tuple2$mcll$sp(cc.x, cc.y)) } }
参考资料
<<Programming in Scala>>第二版
探索Scala(4)-- Case Classes
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。