Какие методы генерируются для кейс-классов Scala?

Какие методы генерируются для кейс-классов Scala?

Я знаю, что некоторые методы генерируются специально для case-классов:

  • равно
  • canEqual

Какие другие?

Кроме того, я вижу, что могу вызывать productArity() для любого класса case. Как это работает? Другими словами, почему следующий код действителен?

case class CaseClass()

object CaseClass {
  val cc = new CaseClass()
  cc.productArity
}

person ilinum    schedule 13.07.2015    source источник


Ответы (3)


Хороший способ сгенерировать методы для конкретного класса в Scala — использовать команду javap.

Найдите файл .class, который был скомпилирован scalac, а затем запустите для него команду javap -private из соответствующего инструмента командной строки. Это покажет вам конструкторы, поля и все методы класса.

Вы можете сделать это для своего класса case, чтобы увидеть, какие вещи автоматически предоставляются Scala.

Классы case смешивают трейт Product, который предоставляет метод productArity. Для классов case метод productArity вернет число из списка параметров, предоставленного в определении класса.

person nattyddubbs    schedule 13.07.2015
comment
Я запустил javap для предоставленного кода и увидел, что он сгенерировал несколько методов. Там были реализованы все методы продукта. Однако был метод productElements(), который возвращал итератор объектов, которые я не получил, откуда он взялся. productElements не находится в продукте. Этот метод где-нибудь объявлен? - person ilinum; 13.07.2015
comment
Не могли бы вы скопировать и вставить сигнатуру метода? - person nattyddubbs; 13.07.2015
comment
public scala.collection.Iterator‹java.lang.Object› productElements(); - person ilinum; 14.07.2015
comment
Итак, используя scalac -print из этого ответа, вот что я получил: @deprecated("use productIterator instead", "2.8.0") def productElements(): Iterator = scala.Product$class.productElements(CaseClass.this); Мы видим, что productElements устарел. - person ilinum; 14.07.2015

Учитывая Test.scala -

case class Test()

Вы можете запустить scalac Test.scala -print, чтобы увидеть, что именно сгенерировано

[[syntax trees at end of                   cleanup]] // Test.scala
package com {
  case class Test extends Object with Product with Serializable {
    <synthetic> def copy(): com.Test = new com.Test();
    override <synthetic> def productPrefix(): String = "Test";
    <synthetic> def productArity(): Int = 0;
    <synthetic> def productElement(x$1: Int): Object = {
      case <synthetic> val x1: Int = x$1;
      case4(){
        matchEnd3(throw new IndexOutOfBoundsException(scala.Int.box(x$1).toString()))
      };
      matchEnd3(x: Object){
        x
      }
    };
    override <synthetic> def productIterator(): Iterator = runtime.this.ScalaRunTime.typedProductIterator(Test.this);
    <synthetic> def canEqual(x$1: Object): Boolean = x$1.$isInstanceOf[com.Test]();
    override <synthetic> def hashCode(): Int = ScalaRunTime.this._hashCode(Test.this);
    override <synthetic> def toString(): String = ScalaRunTime.this._toString(Test.this);
    override <synthetic> def equals(x$1: Object): Boolean = {
  case <synthetic> val x1: Object = x$1;
  case5(){
    if (x1.$isInstanceOf[com.Test]())
      matchEnd4(true)
    else
      case6()
  };
  case6(){
    matchEnd4(false)
  };
  matchEnd4(x: Boolean){
    x
  }
}.&&(x$1.$asInstanceOf[com.Test]().canEqual(Test.this));
    def <init>(): com.Test = {
      Test.super.<init>();
      scala.Product$class./*Product$class*/$init$(Test.this);
      ()
    }
  };
  <synthetic> object Test extends scala.runtime.AbstractFunction0 with Serializable {
    final override <synthetic> def toString(): String = "Test";
    case <synthetic> def apply(): com.Test = new com.Test();
    case <synthetic> def unapply(x$0: com.Test): Boolean = if (x$0.==(null))
      false
    else
      true;
    <synthetic> private def readResolve(): Object = com.this.Test;
    case <synthetic> <bridge> <artifact> def apply(): Object = Test.this.apply();
    def <init>(): com.Test.type = {
      Test.super.<init>();
      ()
    }
  }
}
person Maxim    schedule 13.07.2015
comment
Это отличный ответ. Какую версию scalac вы использовали? Он не генерировал productElements, который устарел с версии 2.8.0. - person ilinum; 14.07.2015

Это правда, что класс case автоматически определяет методы equals и canEqual, но также определяет методы getter для аргументов конструктора. Также есть метод toString, который вы можете вызвать.

Класс case также является экземпляром Product и, таким образом, наследует эти методы. Вот почему вы вызываете productArity.

person alifirat    schedule 13.07.2015