Published 2013-11-06.
Last modified 2024-07-20.
Time to read: 2 minutes.
This lecture continues the exploration of Scala classes.
The sample code for this lecture can be found in
courseNotes/
.
Named Parameters

When reading code containing method calls with many parameters it is often hard to keep track which values are being supplied for various parameters.
If multiple parameters have the same types (for example if several parameters were Boolean
s, String
s or Int
s), it would be easy to mix up the order of the parameters.
That type of bug is very common, especially when there are a lot of parameters to specify. Scala allows all parameters for constructors and methods to be specified by their name; this permits the parameters to be specified in any order.
Unlike JavaScript named arguments and class constructors, Scala methods and constructors do not require any special preparation before they can be invoked using named parameters; all Scala methods and constructors accept named parameters.
Let’s define a Frog2
class.
Like the Frog1
class in the preceding lecture,
Frog2
extends Animal
,
and it adds a toString
method which displays the properties of the object.
The toString
method uses string interpolation to mingle variable values with text.
scala> class Frog2(val canSwim: Boolean,
val numLegs: Int,
val breathesAir: Boolean
) extends Animal(numLegs, breathesAir) {
override def toString = s"Frog2 canSwim=$canSwim, numLegs=$numLegs, breathesAir=$breathesAir"
}
If we create an instance of the Frog2
class without using named parameters,
it is impossible to tell which boolean value corresponds to the canSwim
or breathesAir
parameters
without looking at the class constructor signature.
This is a common source of errors.
scala> val frog2a = new Frog2(true, 4, true) frog3: Frog2a = Frog2 canSwim=true, numLegs=4, breathesAir=true
Lets create an instance of Frog2
using one named parameter.
Because it is also defined as the first parameter and it is placed in its declared position,
the parameter can be named without requiring all the other parameters to also be named.
scala> val frog2b = new Frog2(canSwim=true, 4, true) frog3: Frog2b = Frog2 canSwim=true, numLegs=4, breathesAir=true
Even better, lets name all the boolean parameters.
scala> val frog2c = new Frog2(canSwim=true, 4, breathesAir=true) frog3: Frog2c = Frog2 canSwim=true, numLegs=4, breathesAir=true
Parameter values do not need to be supplied in the order defined in the method signature if named parameters are used. This makes your code more robust.
The best approach is to name all parameters for every constructor and method invocation:
scala> val tadpole = new Frog2(breathesAir=false, canSwim=true, numLegs=0) tadpole: Frog2 = Frog2 canSwim=true, numLegs=0, breathesAir=false

Optional Parameters
None of the Frog2
constructor parameters were defined with default values,
so they all must be specified when the constructor is invoked.
Let’s examine the properties of tadpole1
.
Note that we can use tab completion to list all the properties and methods of the instance.
scala> tadpole.Tab asInstanceOf breathesAir canSwim isInstanceOf msg numLegs toString
scala> tadpole.canSwim res0: Boolean = true

In Scala, parameters to methods can be designated as optional by providing default values.
Let’s create a new class Frog3
which is like Frog2
, but has default values for all parameters.
The rule is that if a method parameter has a default value, then all following parameters must also have default values.
scala> class Frog3(canSwim: Boolean=true, numLegs: Int=4, breathesAir: Boolean=true ) extends Animal(numLegs, breathesAir) { override def toString() = s"canSwim: $canSwim; $numLegs legs; breathesAir:$breathesAir" } // defined class Frog3
scala> val frog3a = new Frog3 frog3a: Frog3 = canSwim: true; 4 legs; breathesAir: true
scala> val frog3b = new Frog3(numLegs=2) frog3b: Frog3 = canSwim: true; 2 legs; breathesAir: true
scala> val frog3c = new Frog3(false) frog3c: Frog3 = canSwim: false; 4 legs; breathesAir: true
scala> val frog3d = new Frog3(false, breathesAir=false) frog3d: Frog3 = canSwim: false; 4 legs; breathesAir: false
Mutable Propoerties
Now let’s define a similar MutableFrog
class with a mutable property, using the var
keyword.
scala> class MutableFrog(val canSwim: Boolean, var numLegs: Int, breathesAir: Boolean ) extends Animal(numLegs, breathesAir) { override def toString = s"MutableFrog canSwim=$canSwim, numLegs=$numLegs, breathesAir=$breathesAir" } // defined class MutableFrog
We can change the value of the mutable property:
scala> val mutableFrog = new MutableFrog(canSwim=true, numLegs=4, breathesAir=true) val mutableFrog: MutableFrog = MutableFrog canSwim=true, numLegs=4, breathesAir=true
scala> mutableFrog.numLegs=2 mutableFrog.numLegs: Int = 2
... but not the immutable properties:
scala> mutableFrog.canSwim=false <console>:10: error: reassignment to val mutableFrog.canSwim=false
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.