案例对象扩展特征的行为差异

时间:2017-06-21 07:30:32

标签: scala

当我遇到Case1片段时,我正在查看github上的一个scala项目来学习scala。特征扩展了Scala Product特征,然后案例对象扩展了该特征。编译得很好。 为了更好地理解这一点,我尝试了Case2似乎没有编译,它要求我在case对象中定义absMethod()。 我不明白为什么在第一种情况下不会发生这种情况。

//Case 1
sealed abstract trait test1 extends Product with Serializable
case object test11 extends test1
test11.productArity  

//Case 2  
trait abstact extends Any{
  def absMethod():Int
}  
sealed abstract trait test2 extends abstact
case object test22 extends test2
test22.absMethod()

2 个答案:

答案 0 :(得分:5)

第一种情况是编译的,因为编译器对案例类/对象具有productArity的特殊知识。作为编译过程的一部分,它不仅会创建一个伴随对象(对于案例类),还会实现多种方法,例如equalshashCodeproductArity(以及更多) 。

如果你看一下typer阶段后的第一个测试的输出(scalac -Xprint:typer):

sealed abstract trait test1 extends AnyRef with Product with Serializable;
  case object test11 extends AnyRef with com.github.yuvalitzchakov.TupleTest.test1 with Product with Serializable {
    def <init>(): com.github.yuvalitzchakov.TupleTest.test11.type = {
      test11.super.<init>();
      ()
    };
    override <synthetic> def productPrefix: String = "test11";
    <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] = scala.runtime.ScalaRunTime.typedProductIterator[Any](test11.this);
    <synthetic> def canEqual(x$1: Any): Boolean = x$1.$isInstanceOf[com.github.yuvalitzchakov.TupleTest.test11.type]();
    override <synthetic> def hashCode(): Int = -877171150;
    override <synthetic> def toString(): String = "test11";
    <synthetic> private def readResolve(): Object = com.github.yuvalitzchakov.TupleTest.test11
}

您可以看到编译器如何实现productArity并指定0(因为对象没有构造函数参数),这在Product上是抽象的。对于自定义定义的抽象方法,您必须自己填充,因此编译器会在找不到实现时抱怨。

答案 1 :(得分:1)

这是因为case object具体而且需要实现其抽象父类。例如,这将起作用并打印42

trait Abstract {
  def method(): Int
}  

sealed trait Test2 extends Abstract

case object Test22 extends Test2 {
  def method(): Int = 42
}

Test22.method()

对于第一种情况,case class es和case objectProduct s,并且它们的字段是在编译时生成的。例如,包含两个字段的case class也是Product,其中包含{2},就像Tuple2[A, B](A, B),一对)。