Scala seamlessly integrates object-oriented and functional programming. Scala is a statically typed language that was conceived in 2001 by Martin Odersky, who also wrote the Java reference compiler and coauthored Java generics. Scala compiles to byte code for the Java Virtual Machine (JVM), making it platform independent. That also means that from a Scala program you can use existing Java libraries, and vice versa.
Getting Started with Scala
You can download Scala from www.scala-lang.org/download/. This Scala software distribution can be installed on any Unix-like or Windows system. It requires the Java runtime version 1.6 or newer.
>scala -version
Scala code runner version 2.10.3 -- Copyright 2002-2013, LAMP/EPFL
There are three ways to execute Scala code.
Using the Interactive Interpreter
The Scala interpreter (called a read-evaluate-print loop, or REPL) is the easiest way to execute a single line of Scala code. You can start the interactive interpreter using the Scala command-line tool scala, which is located in the bin folder in the folder where Scala is installed.
From the command line, enter the following to open the interactive interpreter, shown in Figure C-1.
>scala
Figure C-1. The Scala interactive interpreter
Using the interactive interpreter you can run your first “Hello world” program by using the println method.
scala> println("Hello world");
Hello world
To quit the interpreter, type exit.
scala> exit
Executing Scala Code as a Script
Another way to execute Scala code is to type it into a text file and save it with the extension .scala. You can then execute that code by typing filename.scala. For instance, you can create a file named hello.scala with “Hello world” in it.
println("Hello world")
To execute it, you specify the file name as a parameter to the Scala command-line tool.
>scala hello.scala
Compiling Scala Code
You can also execute Scala code by first compiling it using the scalac command-line tool. Then the code will need to be executed in the context of an application, so you will need to add an object with a main() method (see Listing C-1).
Listing C-1. The “Hello world” Program
1. object HelloWorld {
2. def main(args: Array[String]) {
3. println("Hello, world")
4. }
5. }
Note The semicolon at the end of a statement is usually optional.
def main(args: Array[String]) : Unit = {
}
Save the code in Listing C-1 in a file called HelloWorld.scala and compile the code using the following command:
>scalac HelloWorld.scala
Now run the program using this command:
>scala HelloWorld
Hello, World!
Note Java requires you to put a public class in a file named after the class. For example, you should put class HelloWorld in file HelloWorld.java. In Scala, you can name .scala files anything you want, no matter what Scala classes or code you put in them. However, it is recommended you name files after the classes they contain as is done in Java so as to easily locate classes based on file names.
Variables
Scala allows you to decide whether a variable is immutable (read-only) when you declare it. An immutable variable is declared with the keyword val. This means it is a variable that cannot be changed. Listing C-2 illustrates creating an immutable variable, and Figure C-2 shows what happens when you try to change it.
Listing C-2. Immutable Variable
val immutableVar : String = "Hello"
immutableVar = "Hi"
Figure C-2. Error when trying to change val
Listing C-3 illustrates creating a mutable variable, and Figure C-3 shows it successfully changed.
Listing C-3. Mutable Variable
var mutableVar = "Hello"
mutableVar = "Hi"
Figure C-3. var changed successfully
When you assign an initial value to a variable, the Scala compiler can infer the type of the variable based on the value assigned to it. This is called type inference, as illustrated in Listing C-4.
Listing C-4. Type Inference
var var1= 10
var var2 = "Hello world"
In Listing C-4, Scala will infer var1 to be of the Int type and var2 to be of the String type variable.
Collections
Scala collections distinguish between mutable and immutable collections. A mutable collection can be updated or extended in place. This means you can change, add, or remove elements of a collection as a side effect. Immutable collections, by contrast, never change. You still have operations that simulate additions, removals, or updates, but those operations will in each case return a new collection and leave the old collection unchanged. Scala has a rich collections library. The most commonly used collections are lists, sets, and maps, which are explained in the following sections. You can find details on Scala’s collection library at http://docs.scala-lang.org/overviews/collections/introduction.html.
Lists
Lists are immutable, which means the elements of a list cannot be changed by assignment. The type of a list that has elements of type T is written as List[T], as shown here:
val numberList: List[Integer] = List(1, 2, 3)
Listing C-5 illustrates how to create and use an immutable list.
Listing C-5. Creating an Immutable List
val list = List(1, 2, 3, 2, 3)
println (list.head)
println(list.tail)
println(list.length)
println(list.max)
println(list.min)
println(list.sum)
println(list.sorted)
println(list.reverse)
head --- 1
tail --- List(2, 3, 2, 3)
length --- 5
max --- 3
min --- 1
sum --- 11
sorted --- List(1, 2, 2, 3, 3)
reverse--- List(3, 2, 3, 2, 1)
Scala defines only an immutable list. However, it also defines some mutable list types, such as ArrayBuffer. Listing C-6 illustrates how to create a mutable list.
Listing C-6. Creating a Mutable List
import collection.mutable
val list = mutable.ArrayBuffer(1, 2, 3, 2, 3)
assert (list.length == 5)
Sets
A set is a collection that contains no duplicate elements. There are two kinds of sets, the immutable and the mutable. Listing C-7 illustrates how to create an immutable set.
Listing C-7. Creating an Immutable Set
val set = Set(1, 2, 3, 2, 3)
println ("head -- "+set.head)
println("tail -- "+set.tail)
println("size -- "+set.size)
println("sum -- "+set.sum)
head -- 1
tail -- Set(2, 3)
size -- 3
sum -- 6
By default, Scala uses the immutable set. If you want to use the mutable set, you will have to import scala.collection.mutable.Set. Listing C-8 illustrates how to create and use a mutable set.
Listing C-8. Creating a Mutable Set
import collection.mutable
val set = mutable.HashSet(1, 2, 3, 2, 3)
assert (set.size == 3)
Maps
A Scala map is a collection of key-value pairs. By default, Scala uses the immutable map. If you want to use the mutable map, you’ll have to import the scala.collection.mutable.Map class explicitly. Listing C-9 illustrates how to create and use an immutable map.
Listing C-9. Creating an Immutable Map
val map = Map("1" -> 1, "2" -> 2, "3" -> 3, "2" -> 2, "3" -> 3)
println ("head -- "+map.head)
println("tail -- "+map.tail)
println("size -- "+map.size)
head -- (1,1)
tail -- Map(2 -> 2, 3 -> 3)
size -- 3
Classes in Scala are declared very much like Java classes. One difference is that Scala classes can have parameters, as illustrated in Listing C-10.
Listing C-10. Scala Class with Parameters
class Vehicle (speed : Int){
val mph :Int = speed
def race() = println("Racing")
}
The Vehicle class takes one argument, which is the speed of the vehicle. This argument must be passed when creating an instance of class Vehicle, as follows: new Vehicle(100). The class contains one method, called race().
Extending a Class
It is possible to override methods inherited from a superclass in Scala, as illustrated in Listing C-11.
Listing C-11. Extending a Scala Class
1. class Car (speed : Int) extends Vehicle(speed) {
2. override val mph: Int= speed
3. override def race() = println("Racing Car")
4. }
Listing C-12 illustrates another class called Bike that extends Vehicle.
Listing C-12. Extending a Scala Class
class Vehicle (speed : Int){
val mph :Int = speed
def race() = println("Racing")
}
class Car (speed : Int) extends Vehicle(speed) {
override val mph: Int= speed
override def race() = println("Racing Car")
}
class Bike(speed : Int) extends Vehicle(speed) {
override val mph: Int = speed
override def race() = println("Racing Bike")
}
Save Listing C-12 in the file vehicle.scala and compile it using the following:
>scalac vehicle.scala
Now you can enter the REPL using the scala command and create the vehicle object, as shown here:
scala> val vehicle1 = new Car(200)
With this command, Scala creates the vehicle1 object, as shown here:
vehicle1: Car = Car@19a8942
Now you can use this vehicle1 object created by Scala to access the speed of Car.
scala> vehicle1.mph
The Scala REPL emits the speed of Car, as shown here:
res1: Int = 200
In the similar manner, you can execute the race() method of vehicle1, as shown here:
scala>vehicle1.race()
The Scala interpreter emits the output, as shown here:
Racing Car
Now you can create the Bike object and access its property and method, as shown here:
scala> val vehicle2 = new Bike(100)
vehicle2: Bike = Bike@b7ad3
scala>vehicle2.mph
res4: Int = 100
scala> vehicle2.race()
Racing Bike
Traits
Say you want to add another class to your vehicle hierarchy. This time you want to add a batmobile. A batmobile can race, glide, and fly. But you cannot add glide and fly methods to the Vehicle class because in a nonfictional world, Car and Bike do not glide or fly. Not yet at least. So, if you want to add Batmobile to your vehicle hierarchy, you can use a trait. Traits are like interfaces in Java that can also contain code. In Scala, when a class inherits from a trait, it implements the interface of the trait and inherits all the code contained in the trait. Listing C-13 shows flying and gliding traits.
Listing C-13. Scala Traits
trait flying {
def fly() = println("flying")
}
trait gliding {
def gliding() = println("gliding")
}
Now you can create the Batmobile class that extends Vehicle class along with the flying and gliding traits, as shown in Listing C-14.
Listing C-14. Using Traits
1. Batmobile(speed : Int) extends Vehicle(speed) with flying with gliding{
2. override val mph: Int = speed
3. override def race() = println("Racing Batmobile")
4. override def fly() = println("Flying Batmobile")
5. override def glide() = println("Gliding Batmobile")
6.
7. }
You can now create a batmobile in the REPL, as illustrated here:
scala> val vehicle3 = new Batmobile(300)
vehicle3: Batmobile = Batmobile@374ed5
Now you can access the fly() method of Batmobile, as illustrated here:
scala> vehicle3.fly()
Flying Batmobile
Create a list of vehicles, and then you can use the maxBy() method provided by the Scala collections library to find the fastest vehicle in the list.
scala> val vehicleList = List(vehicle1, vehicle2, vehicle3)
vehicleList: List[Vehicle] = List(Car@562791, Bike@e80317, Batmobile@374ed5)
scala> val fastestVehicle = vehicleList.maxBy(_.mph)
fastestVehicle: Vehicle = Batmobile@374ed5
Singleton Objects
Scala does not have static members. Instead, Scala has singleton objects. A singleton object definition looks like a class definition, except instead of the keyword class you use the keyword object. A singleton is a class that can have only one instance. Listing C-15 illustrates how to use the singleton object in an application.
Listing C-15. Using a Singleton Object in an Application
1. class Vehicle (speed : Int){
2. val mph :Int = speed
3. def race() = println("Racing")
4. }
5. class Car (speed : Int) extends Vehicle(speed) {
6. override val mph: Int= speed
7. override def race() = println("Racing Car")
8.
9. }
10. class Bike(speed : Int) extends Vehicle(speed) {
11. override val mph: Int = speed
12. override def race() = println("Racing Bike")
13.
14. }
15. trait flying {
16. def fly() = println("flying")
17. }
18.
19. trait gliding {
20. def glide() = println("gliding")
21. }
22.
23. class Batmobile(speed : Int) extends Vehicle(speed) with flying with gliding{
24. override val mph: Int = speed
25. override def race() = println("Racing Batmobile")
26. override def fly() = println("Flying Batmobile")
27. override def glide() = println("Gliding Batmobile")
28.
29. }
30. object Vehicle {
31. def main(args: Array[String]) {
32. val vehicle1 = new Car(200)
33. val vehicle2 = new Bike(100)
34. val vehicle3 = new Batmobile(300)
35.
36. val vehicleList = List(vehicle1, vehicle2, vehicle3)
37. val fastestVehicle = vehicleList.maxBy(_.mph)
38.
39. printVehicle
40.
41. def printVehicle{
42. println ("speed of Bike : " + vehicle1.mph);
43. println ("speed of Car : " + vehicle2.mph);
44. println ("speed of Batmobile : " + vehicle3.mph);
45. println ("Fastest Vehicle : " + fastestVehicle.mph + " mph");
46.
47. }
48. }
49. }
When the previous code is compiled and executed, it produces the following result:
>scalac vehicle.scala
>scala Vehicle
speed of Bike : 200 mph
speed of Car : 100 mph
speed of Batmobile : 300 mph
Fastest Vehicle : 300 mph
Summary
This appendix introduced you to the basics of Scala. You learned three ways to interactively execute Scala code as a script and as a compiled program. Then you learned how to use the Scala collections library. Finally, you learned how to use traits and how to use a singleton object in an application.