The first case compiles because the compiler has special knowledge of productArity
for case classes/objects. As part of the compilation process, it will not only create a companion object (for case classes), but also implement several methods, such as equals
, hashCode
, productArity
(and more).
If you look at the output of your first test after the typer phase (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
}
You can see how the compiler implemented productArity
and assigns 0
(since an object has no constructor arguments), which was abstract on Product
. In the case of your custom defined abstract method, you have to fill that on your own, hence the compiler complains when it doesn't find an implementation.
Any
explicitly (a class that extends "nothing" implicitly extendsAny
) and you don't have to annotate yourtrait
asabstract
. - stefanobaghinoAnyRef
. If you have a class extendingAnyVal
and want it to inherit from a trait, that trait needs to extendAny
explicitly. - Jasper-M