I have a constructor, which takes one main argument (data
), and another argument (model
), that has a reasonable default initialization, which depends on the main argument.
I want to have the possibility to give another value for model
whenever that's appropriate.
A simplified example:
1) without default arguments:
class trainer(data:Int,model:Double) {}
2) initialization:
def init(data:Int): Double = 1.0/data
3) it would work if initialization were independent of other arguments:
class trainer(data:Int, model:Double = init(1)) {}
4) what I would like to have, but what gives an error:
class trainer(data:Int, model:Double = init(data)) {}
What's the best/closest way to achieve what I want to do?
(my particular case deals with a constructor, but I would be interested whether there is a way in the general case for functions as well)
Scala provides the ability to give parameters default values that can be used to allow a caller to omit those parameters. The parameter level has a default value so it is optional. On the last line, the argument "WARNING" overrides the default argument "INFO" .
Scala - Functions with Named Arguments Named arguments allow you to pass arguments to a function in a different order. The syntax is simply that each argument is preceded by a parameter name and an equals sign. Try the following program, it is a simple example to show the functions with named arguments.
The thing with optional parameters is, they are BAD because they are unintuitive - meaning they do NOT behave the way you would expect it. Here's why: They break ABI compatibility ! so you can change the default-arguments at one place.
A default argument is a value provided in a function declaration that is automatically assigned by the compiler if the calling function doesn't provide a value for the argument. In case any value is passed, the default value is overridden.
You can simply have an overloaded constructor:
class Trainer(data:Int, model:Double) {
def this(data:Int) = this(data, init(data))
}
Then you can instantiate using:
new Trainer(4)
new Trainer(4, 5.0)
Another approach is to use a companion object with different apply
overloads:
//optionally make the constructor protected or private, so the only way to instantiate is using the companion object
class Trainer private(data:Int, model:Double)
object Trainer {
def apply(data:Int, model:Double) = new Trainer(data, model)
def apply(data:Int) = new Trainer(data, init(data))
}
Then you can instantiate using
Trainer(4)
Trainer(4, 5.0)
Another approach is to use an Option
with a default of None
, and then initialize a private variable in the class body:
class Trainer(data:Int, model:Option[Double] = None) {
val modelValue = model.getOrElse(init(data))
}
Then you instantiate using:
new Trainer(5)
new Trainer(5, Some(4.0))
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