Параметр по умолчанию наследования Scala в родительском классе

У меня есть абстрактный класс со значением по умолчанию для его параметра. Я не хочу повторно использовать значение по умолчанию в конструкторе всех возможных реализаций.

abstract class Place(val place: String = "World")
class Message(val message: String = "Hello", p: String) extends Place(p) {
    override def toString = s"$message $place"
}

Что я хочу получить

new Message("Hi", "Universe") = "Hi Universe" // Ok
new Message("Hi") = "Hi World" // Doesn't work, second parameter is required
new Message() = "Hello World" // Doesn't work, second parameter is required

Я рассматривал возможность использования вспомогательного конструктора без второго параметра, но это не помогает, поскольку вы не можете вызывать суперконструкторы вне основного конструктора.

Я хочу знать, как это сделать или почему это невозможно. Я не ищу обходного пути, например, отказа от наследования.


person user3588254    schedule 19.05.2015    source источник


Ответы (2)


Вы можете повторно использовать значение по умолчанию более элегантным способом:

object Place {
  val defaultPlace = "World"
}
abstract class Place(val place: String = Place.defaultPlace)
class Message(val message: String = "Hello", p: String = Place.defaultPlace) extends Place(p) {
  override def toString = s"$message $place"
}
person Meir Maor    schedule 19.05.2015
comment
работает. не так инкапсулирован. Здесь у вас есть 3 объекта для жонглирования (объект, абстракция и класс). В частности, не следует отдавать должное объекту и реферату, имеющим одно и то же имя. class Message должен знать об объекте Place, поэтому для его использования требуется дополнительная проводка, если это имеет смысл. абстрактное и конкретное должны справиться со всем этим. - person Drew; 19.05.2015

Боюсь, это невозможно. Проще говоря, вы передаете значение конструктору Place, поэтому он не будет использовать значение по умолчанию, каким бы ни было его значение. Если вы не возражаете против использования var вместо val, вот вариант, который работает для ваших 3 случаев:

abstract class Place(var place: String = "World")
class Message(val message: String = "Hello") extends Place()
{
   def this(message: String, place: String) = {
      this(message)
      this.place = place
   }
   override def toString = s"$message $place"
}

Конструкторы в Scala - это немного беспорядок ИМХО. Иногда лучше просто использовать фабричные методы apply() для объекта-компаньона, которые являются более гибкими.

person Daniel Langdon    schedule 19.05.2015