# Scala Tutorial (2)

Scala is a purely object-oriented language in the sense that all language constructs are objects. This includes all primitive type values, such as Char, Int, Long, Float etc. For example, it is perfectly legal in Scala to append a method call to a literal primitive value, as in `3.1415.round`

or `88.max(99)`

. Scala defines the following basic types:

Type | Format | Range |
---|---|---|

Byte | 8-bit Integer | (-2^7 to 2 ^7-1) |

Short | 16-bit Integer | (-2^15 to 2^15-1) |

Int | 32-bit Integer | (-2^31 to 2^31-1) |

Long | 64-bit Integer | (-2^64 to 2^64-1) |

Char | 16-bit Unicode character | (0 to 2^16-1) |

String | A sequence of Chars | |

Float | 32-bit IEEE 754 single-precision floating point number | |

Double | 64-bit IEEE 754 double-precision floating point number | |

Boolean | Logical value | true or false |

These data types are defined in the package `scala`

, which is imported automatically along with `scala.lang`

by the compiler. Extended functionality for these types (such as the cited max() function) is available via the `scala.runtime`

API. Each type has an associated “rich wrapper class”, e.g for `String`

there is a `RichString`

class, for `Int`

there is a `RichInt`

class, and so on. Unlike Java, Scala does not distinguish between objects and primitive types. This implies that there are no boxing and unboxing functions and thus less to worry about the semantic details of these operations. Everything is simply an object. Behind the scenes the compiler performs optimisations that amount to auto-unboxing when arithmetic expressions are evaluated. Hence, the expression `a + b `

which is equivalent to method calls * c*`b.(c).+(a)`

is actually resolved to a primitive type arithmetic, just like in Java.

Scala is not only object-oriented in the sense that all variables are objects, irrespective of type, but that all functions including methods are also objects. Since functions and methods are objects, they are treated just like regular variables, which means that functions can be assigned to variables. They can also be used as parameters in function calls or as return values of functions and methods. A function value in the position of a function parameter creates a so-called higher-order function. In addition, Scala has a construct called a function literal which is basically a nameless function used in place of a function value, a bit like an anonymous method in Java, although the former are a lot more versatile. Furthermore, operators in Scala are methods. This makes some sort of operator overloading possible. Since `+,-,*,/`

etc. are just methods with funny names, you can define operators for your own data types. It is therefore possible to extend the language by adding APIs that contain class definitions for new data types along with their operators. This is illustrated by the following class definition for rational numbers. Rational numbers can be expressed as a fraction of two integer numbers. The following class defines the data type Rational as well as the four basic arithmetic operations for rational numbers:

1 | class Rational(numerator: Int, denominator: Int) { |

The first line contains the head of the class with the so-called primary constructor, which is part of the class declaration in Scala. The expression in parentheses accepts two integer numbers that constitute the numerator and the denominator of the fraction. The next line that starts with `require`

tests the denominator for zero and throws an exception if `denominator = 0`

. As you can see, exceptions don’t need to be declared in the head of the class definition in Scala. The following three lines reduce the fraction by calculating the greatest common divisor and subsequently dividing the numerator and denominator by the result. These first four lines are not enclosed by a function definition block or any other block and thus constitute the body of the primary constructor. Next follows what’s called a auxiliary constructor in Scala. Auxiliary constructors are easy to spot, because they always start with `this()`

. The expression `def this(n: Int) = this(n, 1)`

provides a constructor that accepts a single integer number as an argument. This makes it easy to represent integer numbers as fractions where needed simply by setting the denominator implicitly to 1. For example, the expression `new Rational(2,3)`

results in 2/3 and the expression `new Rational(2)`

results in 2/1.

The method definition that follows the constructor code computes the greatest common integer divisor of two numbers using recursion. Since the recursive invocation stands in tail-call position in this instance, the Scala compiler optimises the generated byte code internally and creates a loop instead of a recursive function call. The four methods after the `greatestCommonDivisor()`

method define the four basic arithmetic operations for fractions. In case of addition and subtraction, the numerators and denominators of both operands are multiplied with each other before the sum of the numerators is calculated. In doing so, Scala makes use of built-in operator precedence (* and / before + and -), which is determined lexically if the function or method name begins with a special operator characters. The expression n * that.d + d

*that.n, is thus executed as*(that.d).+.(d.*(that.n)). Multiplication and division are even easier to implement as the two fractions are simply multiplied by each other, or respectively multiplied by the reciprocal value. The results are then returned as new

`n.`

`Rational`

objects. Since the constructor finds the GCD of the two integer numbers, the resulting fraction is automatically reduced. Finally, the last method `toString`

outputs the fraction in a readable form. Overridden methods must be marked with the `override`

keyword in Scala. Functions that don’t take arguments are written without parentheses, hence `toString()`` becomes ``toString`

.

**Class Hierarchy**

Similar to Smalltalk, every class inherits from a single common superclass. The universal superclass is named `Any`

in Scala. This is to say that any datum in Scala is of the type `Any`

. The subclasses of `Any`

fall into two categories: `AnyVal`

(value) and `AnyRef`

(object reference). The above listed basic data types, as well as the primitive types in Java, such as `byte, int, float,`

etc., are direct descendants of `AnyVal`

, while all other types are descendants of `AnyRef`

. The Scala type `AnyRef`

is therefore conceptually identical with `java.lang.Object`

and it comes with analogous methods, e.g. `equals(), hashCode, clone, wait,`

etc. Some of these are actually defined further up in the hierarchy, namely in `Any`

. In addition, Scala defines the type `scala.scalaObject`

which provides the common superclass for all objects in the Scala APIs. This works because Scala allows multiple inheritance via so-called traits. This will be explained later in more detail.

The nesting of this type hierarchy allows interoperability wit Java. For example:

1 | var a: int = 2 // Java Integer |

In addition, it is possible to use Java collections for storing Scala data types, or Scala collections for storing Java data types. Furthermore, Scala has several special data types. For example, `scala.Null`

is defined as subtype of any class that derives from an object reference `scala.AnyRef`

. It is analogous to the `null`

literal in Java and can thus be assigned to object references. The type `scala.Nothing`

is defined as a subtype of all types; it is employed in exceptions where an expression does not return a type. This happens situations where an exception is thrown in a place where a value is expected. Finally, there is the type `scala.Unit`

that is used for functions that don’t return a value. This is Scala’s concession to imperative programming. It is analogous to the `void`

keyword in Java.