Consider the following class written in Java:
class NonNegativeDouble {
private final double value;
public NonNegativeDouble(double value) {
this.value = Math.abs(value);
}
public double getValue() { return value; }
}
It defines a final field called value
that is initialized in the constructor, by taking its parameter called alike and applying a function to it.
I want to write something similar to it in Scala. At first, I tried:
class NonNegativeDouble(value: Double) {
def value = Math.abs(value)
}
But the compiler complains: error: overloaded method value needs result type
Obviously the compiler thinks that the expression value
inside the expression Math.abs(value)
refers to the method being defined. Therefore, the method being defined is recursive, so I need to state its return type. So, the code I wrote does not do what I expected it to do: I wanted value
inside Math.abs(value)
to refer to the constructor parameter value
, and not to the method being defined. It is as if the compiler implicitly added a this.
to Math.abs(this.value)
.
Adding val
or var
(or private ...
variants) to the constructor parameter doesn't seem to help.
So, my question is: can I define a property with the same name as a constructor parameter, but maybe a different value? If so, how? If not, why?
Thanks!
We can have any number of Parameterized Constructor in our class. In this example, I have implemented four constructors: one is default constructor and other three are parameterized. During object creation the parameters we pass, determine which constructor should get invoked for object initialization.
If the parameters in the constructor parameter-list are declared using var, then the value of the fields may change. And Scala also generates getter and setter methods for that field. If the parameters in the constructor parameter-list are declared using val, then the value of the fields cannot change.
Constructors can also take parameters, which is used to initialize attributes.
Constructors in Scala describe special methods used to initialize objects. When an object of that class needs to be created, it calls the constructor of the class. It can be used to set initial or default values for object attributes.
No, you can't. In Scala, constructor parameters are properties, so it makes no sense to redefine them.
The solution, naturally, is to use another name:
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
Used like this, initValue
won't be part of the instances created. However, if you use it in a def
or a pattern matching declaration, then it becomes a part of every instance of the class.
@Daniel C. Sobral
class NonNegativeDouble(initValue: Double) {
val value = Math.abs(initValue)
}
your code is right, but "constructor parameters are properties",this is not true.
A post from the official site said,
A parameter such as class Foo(x : Int) is turned into a field if it is referenced in one or more methods
And Martin's reply confirms its truth:
That's all true, but it should be treated as an implementation technique. That's why the spec is silent about it.
So normally, we can still treat primary constructor parameters as normal method parameter, but when the parameters is referenced by any of the methods, the compiler will cleverly turn it into a private field.
If any formal parameter preceded by the val, the compiler generates an getter definition automatically.if var, generates a setter additionally. see the language speification section 5.3.
That's all about primary constructor parameters.
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