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(模式匹配时使用)方法

posted on 2015-03-09 12:20  Ai_togic  阅读(152)  评论(0编辑  收藏  举报

导航