Метод применения по умолчанию класса Case

Предполагая, что мы имеем следующий класс case:

case class CasePerson(firstName: String)

И мы также определяем для него объект-компаньон:

object CasePerson {
 def apply() = new CasePerson( "XYZ" )
}

Обратите внимание, что в приведенном выше примере я явно определил объект-компаньон с помощью метода apply, не определяя метод применения по умолчанию:

// This "default" apply has the same argument as the primary constructor of the case class
def apply(firstName : String) = new CasePerson(firstName)

Q: Итак, где применяется Scala этот "по умолчанию"? Я явно определил объект-компаньон здесь без применения по умолчанию, и компилятор все еще знает, как это выполнить:

val casePerson = CasePerson("PQR")

Как это работает?

Ответ 1

Scala классы case - это синтаксический сахар. Когда вы создаете класс case, компилятор Scala создаст сопутствующий объект с помощью метода apply и unapply, который вы можете использовать, как если бы он просто существовал. Здесь - ссылка на более подробную информацию о классах case.

Ответ 2

Классы классов неявно сопровождаются сопутствующим объектом с apply(), который имеет те же аргументы, что и основной конструктор класса case.

То есть:

case class CasePerson(firstName: String)

Будет сопровождаться

object CasePerson{
   def apply(firstName: String) = new CasePerson(firstName)
}

Теперь, если вы также явно определяете объект-компаньон, вы можете думать об этом как о добавлении к неявно определенному.

Например, в вашем примере вы добавили один новый apply к сопутствующему объекту:

object CasePerson{
   def apply() = new CasePerson("XYZ")
}

Этот оператор, вы можете думать об этом, как будто он создает объединенный объект-компаньон:

object CasePerson{
   def apply() = new CasePerson("XYZ") // the one manually added
   def apply(firstName: String) = new CasePerson(firstName) // this one is automatically added
}

Теперь, если вы решите добавить свою собственную версию apply, которая имеет те же аргументы, что и основной конструктор, это затмит поведение по умолчанию класса case.

object CasePerson{
   def apply() = new CasePerson("XYZ")
   def apply(s: String) = Seq(new CasePerson(s), new CasePerson(s)) // will replace the default factory for the case class
}

Теперь, если вы вызываете CasePerson("hi"), он будет генерировать:

List(CasePerson("hi"), CasePerson("hi"))

Ответ 3

Вы также можете присвоить параметру класса firstName значение по умолчанию. Таким образом, вы можете создать экземпляр с отсутствием параметра.

Пример:

case class CasePerson(firstName : String = "XYZ")
val person = CasePerson()