Published 2013-11-06.
Last modified 2024-07-20.
Time to read: 6 minutes.
This lecture continues the exploration of Scala classes.
Variable Number of Arguments (varargs)
Sometimes it is desirable to write a method that accepts an arbitrary number of arguments of a certain type, and for one reason or another it is undesirable to provide a collection.
If you are a Java programmer, your are familiar with the
Java varargs syntax.
A Java vararg
is presented to the method body as an array.
Here is a modified version of Oracle’s Java varargs example that actually runs.
This code is provide as courseNotes/src/main/java/VarArgsJava.java
.
import java.awt.Polygon; import java.awt.Point;
public class VarArgsJava { public static Polygon polygonFrom(Point...points) { Polygon polygon = new Polygon(); for (Point point: points) polygon.addPoint(point.x, point.y); return polygon; }
public static void main(String[] args) { Polygon square = polygonFrom(new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0)); System.out.println("Bounding box of polygon is: " + square.getBounds2D()); } }
Output is:
Bounding box of polygon is: java.awt.Rectangle[x=0,y=0,width=1,height=1]
Scala’s varargs syntax is slightly different, but also easily recognizable: a variable name and type are specified as usual, followed by an asterisk. The asterisk indicates to the compiler that a variable number of values of the specified type can be supplied.
A Scala vararg is made available to the body of the method as a Seq
instead of an Array
.
We’ll learn about Seq
in the
Collections Overview
lecture of the Intermediate Scala
course but for now suffice it to say that a Seq
is a collection that can be iterated over.
The Scala equivalent of the above Java code is:
object VarArgsScala extends App { import java.awt.{Polygon, Point}
/** @return a polygon connecting the given points */ def polygonFrom(points: Point*): Polygon = { val polygon = new Polygon() points.foreach { point => polygon.addPoint(point.x, point.y) } polygon }
val square = polygonFrom(new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0)) println(s"Bounding box of polygon is: ${square.getBounds2D}") }
Output is the same as the Java version.
There are two restrictions on when Scala varargs can be used:
- The vararg parameter must be the last parameter in the method’s parameter list
- A method with a varargs parameter cannot define default values for any of its parameters

Splatting an Seq or Array
_*
is placeholder notation that indicates a Seq[T]
or Array[T]
should be provided to a method that accepts varargs of type T
.
We will discuss type parameters in the
Parametric Types lecture of the
Intermediate Scala course.
For the curious: this placeholder notation tells the compiler to modify the mechanics of this particular method invocation,
without modifying the collection.
We can use this placeholder notation to rewrite the above invocation of polygonFrom
.
val points = List(new Point(0, 0), new Point(0, 1), new Point(1, 1), new Point(1, 0))
val square2 = polygonFrom(points: _*)
println(s"Bounding box of polygon is: ${square2.getBounds2D}")
Output is the same as above.
An asterisk is often referred to as splat in computer science, thus this placeholder syntax is sometimes referred to as placeholder splat.
We will see another usage of this placeholder notation in the Pattern Matching on Collections lecture of the Intermediate Scala course.

Anonymous Classes
Classes that do not have a name are called anonymous classes. Their primary constructor cannot accept any parameters. Here is an example.
val adhoc = new { def test(predicate: Boolean): String = if (predicate) "Yes" else "No" }
Let’s use this anonymous class.
scala> adhoc.test(3>2) res7: String = Yes
You can also run this from the console by typing.
$ sbt "runMain animals.Anonymous1"

BTW, anonymous functions are often called lambda functions, or even just lambdas. Anonymous classes can also be created by extending an existing class, trait, or Java interface. We will cover traits in the Scala Traits lecture.
If the definition being extended has any abstract members, they must be implemented in the body of the anonymous class. The syntax is similar to how this is implemented in Java.
Let’s use the REPL to extend java.util.Date
by defining an anonymous class that adds a new method called dayAfter
.
scala> import java.util.Date import java.util.Date
scala> val myDate = new Date { | def dayAfter = new Date(getTime + 1000L*60L*60L*24L) | } myDate: java.util.Date{def dayAfter: java.util.Date} = Sun Oct 27 22:13:22 PDT 2013
scala> myDate.dayAfter res1: java.util.Date = Mon Oct 28 22:13:22 PDT 2013
You can also run this from the console by typing.
$ sbt "runMain animals.Anonymous2"

Here is an example of extending a class with an anonymous class.
As we have seen before, the REPL invokes the class’s toString
method after creating the instance.
The toString
method for this subclass concatenates the value returned by the superclass’s toString
method with our French frog’s favorite food.
scala> val grenouille = new Frog4 { | var favoriteFood = "insects" | override def toString = super.toString + s" favorite food=$favoriteFood" | } grenouille: Frog4{def favoriteFood: String; def favoriteFood_=(x$1: String): Unit} = canSwim: true; 4 legs; breathesAir:true; favorite food=insects
You can also run this from the console by typing:
$ sbt "runMain animals.Anonymous3"
Anonymous Subclass of an Abstract Class
There is nothing to prevent someone from defining an anonymous class from the Animal
abstract class and creating an instance, like this.
scala> val naughty = new Animal(4, true) {} naughty: Animal = $anon$1@4c398c80
This same trick works with traits. The only requirement is that the superclass must not have any abstract methods or properties.
Bad Habit: Defining Too Many Anonymous Classes

It is easy to get in the habit of defining an anonymous class even though a concrete class would be equally convenient. Here are some reasons for why this is a bad habit.
- Anonymous classes cannot be reused because each instance is unique.
- Anonymous classes take up the same memory space and require the same overhead as concrete classes, so if you created large quantities of them your program will become bloated and slow.
- Anonymous classes cannot be tested because each instance is unique.
For example, here we define an anonymous class that extends Frog3
and overrides the standard method toString
.
scala> val frog3b = new Frog3(canSwim=true, 4, breathesAir=true) { | override def toString = s"$canSwim; $numLegs legs" | } res6: Frog3 = true; 4 legs; breathesAir=true
scala> grenouille.favoriteFood res0: String = insects
scala> grenouille.canSwim res1: Boolean = true
The good habit is to define a similar concrete class as the anonymous class above. This would be desirable to do if we needed more than one instance, or you wanted to be able to test it.
scala> class Frog5(override val canSwim: Boolean=true, breathesAir: Boolean=true ) extends Frog3(canSwim, 4, breathesAir) { | override def toString = s"canSwim: $canSwim; $numLegs legs; breathesAir: $breathesAir" | } defined class Frog5
scala> val frog5 = new Frog5(canSwim=true, breathesAir=true) frog5: Frog5 = canSwim: true; 4 legs; breathesAir: true

Operator Overloading
Scala allows you to create multiple methods with the same name that accept different parameters.
Let’s define a complex number class that defines binary addition and a unary negation operator.
Note how the unary minus sign operator is preceded with unary_
so the compiler knows what we mean.
class Complex(val re: Double, val im: Double) { def +(another: Complex) = new Complex(re + another.re, im + another.im)
def unary_- = new Complex(-re, -im)
override def toString = s"$re + ${im}i" }
Scala allows methods to be defined called unary_!
, unary_~
, unary_+
and unary_-
.
Now let’s use this definition in some complex arithmetic operations.
scala> val c1 = new Complex(2, 5) + new Complex(1, -2) // infix notation c1: Complex = 3.0 + 3.0i
scala> val c2 = new Complex(2, 5).+(new Complex(1, -2)) // same computation using dot notation c2: Complex = 3.0 + 3.0i
scala> val c3 = -c1 c3: Complex = -3.0 + -3.0i
scala> val c4 = -new Complex(2, 5) c4: Complex = -2.0, -5.0i
scala> val c5 = - c1 // space after unary operator is optional c5: Complex = -3.0 + -3.0i
scala> val c6 = (new Complex(1, -2)).unary_- // this syntax is of academic interest only c6: Complex = -1.0 + 2.0i
Types vs. Classes
This section has been paraphrased from James Iry’s Stack Overflow posting (James worked on the Scala compiler). Some of this explanation goes beyond the material of this course, and some of it goes beyond the material of the Intermediate Scala course.
A static type is a property of a portion of a program that can be statically proven,
that is proven correct without running the program.
In a statically typed language, every expression has a type whether you write it or not.
For instance, in the following Scala snippet, a
, b
, c
, and d
have types,
a * b
has a type, a * b + c
has a type and a * b + c - d
has a type,
even though only x
is explicitly annotated with a type.
val a = 3 val b = 2.0 val c = 5L val d = 4.2 val x: Int = a * b + c - d
A Scala class, on the other hand, is just the specification for a set of objects. That specification includes some type information and includes a lot of implementation and representation details such as method bodies and private fields, etc. In Scala a class also specifies some module boundaries.
Many languages have types but don’t have classes and many languages have classes but don’t have (static) types.
There are several observable differences between types and classes.
List[String]
is a type but not a class.
A Scala List
is a class, but normally not a type (it’s actually a higher-kinded type).
In Java, List
is a raw type.

Scala offers structural types (discussed in the
Structural Types lecture of the
Intermediate Scala course).
For example, { def foo: Bar }
means any object that has a foo
method which returns a Bar
.
It’s a type, but not a class.
Types can be abstracted using type parameters (discussed in the Parametric Types of the Intermediate Scala course). When you write:
def foo[T](x: T) = { /* whatever */ }
then inside the body of foo
, T
is a type, however T
need not be a class.
Scala types can be virtual (i.e. "abstract type members"), but Scala classes can’t be virtual.
Dynamic types are properties of objects that the language runtime automatically checks before performing certain operations.
In dynamically typed class-based OO languages there’s a strong correlation between types and classes.
The same thing happens on JVM languages such as Scala and Java which have operations that can only be checked dynamically such as reflection and casting.
In those languages, type erasure more or less means that the dynamic type of most objects is the same as their class.
That’s not true of, arrays whose types are preserved so that the Java runtime can tell the difference between Array[Int]
and Array[String]
.
When you use reflection it is possible to invoke any message on any object. If the object supports that method then everything works out. Thus it makes sense to talk of all objects that can quack like a duck as a dynamic type, even though they are not defined as a class. Scala calls this structural types, and the Python and Ruby communities call this duck typing.
Finally, there are types like Int
which don’t have a class as an implementation detail, types like Null
and Any
which are a bit special but could have classes and don’t, and types like Nothing
which doesn’t even have any values let alone a class.
© 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.