Search code examples
scalatraitscons

Scala: "apply" method in companion are required to create case class instance?


The below code defines a List type and two implementation of case classes one representing empty list and Cons to create actual list

sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]

object List {
  ...
  def apply[A](as: A*): List[A] = {
    if (as.isEmpty) Nil
    else Cons(as.head, apply(as.tail: _*))
  }
  val example = Cons(1, Cons(2, Cons(3, Nil)))
}

is my assumption correct that the list is created by the recursive apply method above when the val example = ... is executed.

if that is so. the signature for creating Cons is Cons(head, tail) where as the signature of the apply is incompatible variad def apply[A](as: A*): List[A], how does scala actually infers the val example to be List(1, 2, 3, Nil)


Solution

  • When you say

    class Foo(s: String, i: Int)
    

    in scala, it generates a class Foo with a constructor taking a String and an Int.

    It's pretty much the same as a java class declared as

    public class Foo {
       public Foo(String s, int i) {
           ...
       }
    }
    

    With case classes, the compiler provides extra-goodies such as a companion object with a default apply method taking the same parameters as the constructor.

    So that's why you can directly call Cons(head, tail), without explicitly define a constructor.