Можно ли наследовать вспомогательные конструкторы в Scala? - PullRequest
1 голос
/ 25 сентября 2010

Интересно, можно ли наследовать вспомогательные конструкторы в Scala?

Я проверил этот код, и он пожаловался

temp.scala: 18: ошибка: слишком много аргументов для конструктора Child: () this.Child

val a = new Child (42)

   ^
abstract class Father {
 var value: Int = 0

 protected def setValue(v: Int) = {
  value = v
 }

 protected def this(v: Int) = {
  this()
  setValue(v)
 }
}

class Child extends Father {
}

val a = new Child(42)

Но если я поставлю

protected def this(v: Int) = {
    this()
    setValue(v)
}

в классе Child, все в порядке.

Ответы [ 2 ]

2 голосов
/ 27 сентября 2010

Абсолютно нет, и ваш пример демонстрирует почему. Вы ввели изменчивую переменную value, которая может быть инициализирована или не инициализироваться - в зависимости от используемого конструктора.

Это потенциальный источник для множества проблем, и поэтому Scala приняла решение, что создание всех объектов в конечном итоге должно осуществляться через первичный конструктор, что обеспечивает согласованную инициализацию.

Если вы хотите, чтобы value имел значение по умолчанию, вы можете указать его как параметр по умолчанию (в 2.8 +):

abstract class Father(val value : Int = 0)

или вы можете использовать вспомогательный конструктор для достижения того же эффекта в Scala 2.7:

abstract class Father(val value : Int) {
  def this() = this(0)
}

Если Father определен любым из вышеперечисленных способов, оба следующих определения child являются действительными:

class Child(v:Int) extends Father(v)

class Child extends Father()

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

Если семантика value означает, что допустимо не инициализироваться, то правильная идиома Scala - объявить ее как Option[Int]:

abstract class Father(val value : Option[Int] = Some(0))
1 голос
/ 25 сентября 2010

У вашего конструктора Child нет параметров, и вы пытаетесь создать его с одним!Вы должны объявить параметр в конструкторе Child и затем передать его классу Father, например:

class Child(v:Int) extends Father(v) {
}

val a = new Child(42)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...