Параметр наследования 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

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

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

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"
}

Я боюсь, что это не возможно. Проще говоря, вы передаете значение конструктору места, поэтому он не будет использовать значение по умолчанию, каким бы ни было его значение. Если вы не возражаете иметь 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-это немного беспорядок ИМХО. Иногда лучший ответ - это просто использовать методы factory apply() на сопутствующем объекте, которые являются более гибкими.