Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala constructor with default arg referencing another arg

I would to make the second constructor argument optional, and use the value of the first argument in that case. Is there any way I can do that ? This code doesn't compile as it can't find realUser:

class CurrentUser(val realUser:String, val masqueradeUser:String = realUser)

I'm sure I can work around it by writing my own constructor, but I wondered if there were a more concise way. Actually now that I've tried writing my own constructor, it isn't that bad:

class CurrentUser(val realUser:String, val masqueradeUser:String) {
    def this(realUser:String) = this(realUser, realUser)
}

If someone can come up with something shorter then great, otherwise I'll post my own answer.

like image 384
Nick Avatar asked Oct 20 '11 10:10

Nick


People also ask

What is the benefit of giving a constructor default arguments?

Supplying default constructor parameters has at least two benefits: You provide preferred, default values for your parameters. You let consumers of your class override those values for their own needs.

How do I set default value in Scala?

You can assign a default value for a parameter using an equal to symbol. I gave a default value for the first parameter. If the caller doesn't pass any value for the first parameter, Scala will take the default value as println. That's it.

What is the default Behaviour of Scala method?

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

What are the parameters that are default values?

A parameter with a default value, is often known as an "optional parameter". From the example above, country is an optional parameter and "Norway" is the default value.


3 Answers

I believe your solution with the auxiliary constructor is the better one. A parameter is not visible in its own parameter list, only in the following ones. So you would have to do

class CurrentUser(val realUser: String)(val masqueradeUser: String = realUser)

and then call with

new CurrentUser(real)()

Not too nice.

like image 51
Didier Dupont Avatar answered Nov 16 '22 01:11

Didier Dupont


You can’t reuse parameters from the same parameter list as default arguments. didierd’s solution works, and probably your solution with a second constructor is the most elegant. Here's a third alternative, which uses the dreaded null:

scala> class CurrentUser(val realUser:String, _masqueradeUser: String = null) {
     |   val masqueradeUser = if (_masqueradeUser == null) realUser else _masqueradeUser
     | }
defined class CurrentUser

scala> new CurrentUser("paul").masqueradeUser
res1: String = paul

scala> new CurrentUser("paul", "p").masqueradeUser
res2: String = p

If you want to avoid null, you can use the Opt[A] class discussed here if you don't mind the overhead. One way or another, I’d still go with your second-constructor solution.

like image 36
Jean-Philippe Pellet Avatar answered Nov 16 '22 01:11

Jean-Philippe Pellet


Thanks for the suggestions. I think I will stick with specifying the second constructor form manually. Here it is as an answer for completeness' sake.

class CurrentUser(val realUser:String, val masqueradeUser:String) {
    def this(realUser:String) = this(realUser, realUser)
}
like image 5
Nick Avatar answered Nov 16 '22 02:11

Nick