case class 背后的秘密
scala中做模式匹配时,会用到case class (样本类) 和 extractor (抽取器),这种class 前面加一个case后,与普通的class有什么区别呢?下面我们来一探究竟。
先写个普通的class Person, 为了更好的说明问题,我们尽量简化这个Person。
scala> class Person { var name: String = _ } [[syntax trees at end of typer]] // <console> package $line3 { object $read extends scala.AnyRef { def <init>(): $line3.$read.type = { $read.super.<init>(); () }; object $iw extends scala.AnyRef { def <init>(): type = { $iw.super.<init>(); () }; object $iw extends scala.AnyRef { def <init>(): type = { $iw.super.<init>(); () }; class Person extends scala.AnyRef { def <init>(): Person = { Person.super.<init>(); () }; private[this] var name: String = _; <accessor> def name: String = Person.this.name; <accessor> def name_=(x$1: String): Unit = Person.this.name = x$1 } } } } } [[syntax trees at end of typer]] // <console> package $line3 { object $eval extends scala.AnyRef { def <init>(): $line3.$eval.type = { $eval.super.<init>(); () }; private[this] val $print: String = { $read.$iw.$iw; "defined class Person\n" }; <stable> <accessor> def $print: String = $eval.this.$print } } defined class Person
我们再来定义一个case class, 看看编译器都为我们做了哪些工作?
scala> case class Person { var name: String = _ } [[syntax trees at end of typer]] // <console> package $line4 { object $read extends scala.AnyRef { def <init>(): $line4.$read.type = { $read.super.<init>(); () }; object $iw extends scala.AnyRef { def <init>(): type = { $iw.super.<init>(); () }; object $iw extends scala.AnyRef { def <init>(): type = { $iw.super.<init>(); () }; case class Person extends AnyRef with Product with Serializable { def <init>(): Person = { Person.super.<init>(); () }; private[this] var name: String = _; <accessor> def name: String = Person.this.name; <accessor> def name_=(x$1: String): Unit = Person.this.name = x$1; <synthetic> def copy(): Person = new Person(); override <synthetic> def productPrefix: String = "Person"; <synthetic> def productArity: Int = 0; <synthetic> def productElement(x$1: Int): Any = x$1 match { case _ => throw new IndexOutOfBoundsException(x$1.toString()) }; override <synthetic> def productIterator: Iterator[Any] = runtime.this.ScalaRunTime.typedProductIterator[Any](Person.this); <synthetic> def canEqual(x$1: Any): Boolean = x$1.$isInstanceOf[Person](); override <synthetic> def hashCode(): Int = ScalaRunTime.this._hashCode(Person.this); override <synthetic> def toString(): String = ScalaRunTime.this._toString(Person.this); override <synthetic> def equals(x$1: Any): Boolean = x$1 match { case (_: Person) => true case _ => false }.&&(x$1.asInstanceOf[Person].canEqual(Person.this)) }; <synthetic> object Person extends scala.runtime.AbstractFunction0[Person] with Serializable { def <init>(): Person.type = { Person.super.<init>(); () }; final override <synthetic> def toString(): String = "Person"; case <synthetic> def apply(): Person = new Person(); case <synthetic> def unapply(x$0: Person): Boolean = if (x$0.==(null)) false else true; <synthetic> private def readResolve(): Object = $iw.this.Person } } } } } warning: there were 1 deprecation warning(s); re-run with -deprecation for details [[syntax trees at end of typer]] // <console> package $line4 { object $eval extends scala.AnyRef { def <init>(): $line4.$eval.type = { $eval.super.<init>(); () }; private[this] val $print: String = { $read.$iw.$iw; "defined class Person\n" }; <stable> <accessor> def $print: String = $eval.this.$print } } defined class Person
可以看到,编译器为我们做了很多工作:
1. 增加toString, hasCode, equals方法等。
2. 增加伴生类对象,这个伴生类对象实现了apply(构建对象时,不需要new关键字), unapply(模式匹配时使用)方法