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.
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.
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"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With