Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala inheritance default parameter in parent class

I have an abstract class with a default value for its parameter. I don't want to have to reuse the default value in the constructor of all the possible implementations.

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

What I want to get

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

I considered using an auxiliary constructor omitting the second parameter, but it doesn't help since you can't call super constructors outside of the main constructor.

I want to know how to do it, or why it is not possible. I'm not looking for a workaround, like not using inheritance.

like image 724
user3588254 Avatar asked May 19 '15 12:05

user3588254


2 Answers

I'm afraid that is not possible. Quite simply, you ARE passing a value to Place constructor, so it wont use the default, whatever its value might be. If you don't mind having a var instead of a val, here is a variant that works for your 3 cases:

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

Constructors in Scala are a little of a mess IMHO. Sometimes a better answer is just to use factory apply() methods on a companion object, which are more flexible.

like image 200
Daniel Langdon Avatar answered Oct 22 '22 03:10

Daniel Langdon


You can reuse the default value in a more elegant way:

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"
}
like image 22
Meir Maor Avatar answered Oct 22 '22 02:10

Meir Maor