diff options
Diffstat (limited to 'doc/tutorial/ScalaTutorial.scala.tex')
-rw-r--r-- | doc/tutorial/ScalaTutorial.scala.tex | 778 |
1 files changed, 0 insertions, 778 deletions
diff --git a/doc/tutorial/ScalaTutorial.scala.tex b/doc/tutorial/ScalaTutorial.scala.tex deleted file mode 100644 index 512417da0e..0000000000 --- a/doc/tutorial/ScalaTutorial.scala.tex +++ /dev/null @@ -1,778 +0,0 @@ -%% This file really contains -*- LaTeX -*- code, to be processed by -%% the scalatex script. - -%% $Id$ - -\documentclass[a4paper,12pt,twoside,titlepage]{article} - -\usepackage{scaladoc} -\usepackage{xspace} - -\ifpdf - \pdfinfo { - /Author (Michel Schinz) - /Title (A Scala Tutorial) - /Keywords (Scala programming language tutorial) - /Subject (Basic introduction to Scala, mostly for Java programmers) - /Creator (TeX) - /Producer (PDFLaTeX) - } -\fi - -\renewcommand{\doctitle}{A Scala Tutorial \\ -\large for Java programmers \ } -\renewcommand{\docsubtitle}{Version 1.0} -\renewcommand{\docauthor}{Michel Schinz\\[65mm]} - -\newcommand{\langname}[1]{#1\xspace} - -\newcommand{\Scala}{\langname{Scala}} -\newcommand{\Java}{\langname{Java}} - -\newcommand{\toolname}[1]{\texttt{#1}\xspace} - -\newcommand{\scalac}{\toolname{scalac}} -\newcommand{\scala}{\toolname{scala}} -\newcommand{\java}{\toolname{java}} - -\begin{document} -\makedoctitle - -\section{Introduction} -\label{sec:introduction} - -This document gives a quick introduction to the \Scala language and -compiler. It is intended for people who already have some programming -experience and want an overview of what they can do with \Scala. A -basic knowledge of object-oriented programming, especially in \Java, -is assumed. - -\section{A first example} -\label{sec:first-example} - -As a first example, we will use the standard \emph{Hello world} -program. It is not very fascinating but makes it easy to demonstrate -the use of the \Scala tools without knowing too much about the -language. Here is how it looks: -\begin{scalaprogram}{HelloWorld} -object HelloWorld { - def main(args: Array[String]): unit = { - System.out.println("Hello, world!"); - } -} -\end{scalaprogram} - -The structure of this program should be familiar to Java programmers: -it consists of one method called \code{main} which takes the command -line arguments, an array of strings, as parameter; the body of this -method consists of a single call to the \code{println} method of the -object representing the standard output, with the friendly greeting as -argument. The \code{main} method is declared as returning a value of -type \code{unit}, which for now can be seen as similar to \Java's -\code{void} type. - -What is less familiar to Java programmers is the \code{object} -declaration containing the \code{main} method. Such a declaration -introduces what is commonly known as a \emph{singleton object}, that -is a class with a single instance. The declaration above thus declares -both a class called \code{HelloWorld} and an instance of that class, -also called \code{HelloWorld}. This instance is created on demand, -the first time it is used. - -The astute reader might have noticed that the \code{main} method is -not declared as \code{static} here. This is because static members -(methods or fields) do not exist in \Scala. Rather than defining static -members, the \Scala programmer declares these members in singleton -objects. - -\subsection{Compiling the example} -\label{sec:compiling-example} - -To compile the example, we use \scalac, the \Scala compiler. \scalac -works like most compilers: it takes a source file as argument, maybe -some options, and produces one or several object files. The object -files it produces are standard \Java class files. - -If we save the above program in a file called -\code{HelloWorld.scala}, we can compile it by issuing the following -command (the greater-than sign `\verb|>|' represents the shell prompt -and should not be typed): -\begin{verbatim} -> scalac HelloWorld.scala -\end{verbatim} -This will generate a few class files in the current directory. One of -them will be called \code{HelloWorld.class}, and contains a class -which can be directly executed using the \scala command, as the -following section shows. - -\subsection{Running the example} -\label{sec:running-example} - -Once compiled, a \Scala program can be run using the \scala command. -Its usage is very similar to the \java command used to run \Java -programs, and accepts the same options. The above example can be -executed using the following command, which produces the expected -output: -\begin{verbatim} -> scala -classpath . HelloWorld -\end{verbatim} -\scalaprogramoutput{HelloWorld} - -\section{Interaction with Java} -\label{sec:inter-with-java} - -One of the strength of \Scala is that it makes it very easy to -interact with \Java code. Actually, the example of the previous -section showed this: to print the message on screen, we simply used a -call to \Java's \code{println} method on the (\Java) object -\code{System.out}. - -All \Java code is accessible as easily from \Scala. Like in \Java, all -classes from the \code{java.lang} package are imported by default, -while others need to be imported explicitly. - -Let's look at another example to see this. The aim of this example is -to compute and print the factorial of 100 using \Java big integers -(i.e. the class \code{BigInteger} in package \code{java.math}), -since the result does not fit in a \Java integer. This program looks -like this: -\begin{scalaprogram}{BigFactorial} -object BigFactorial { - import java.math.BigInteger, BigInteger._; - - def fact(x: BigInteger): BigInteger = - if (x == ZERO) ONE - else x multiply fact(x subtract ONE); - - def main(args: Array[String]): unit = - System.out.println("fact(100) = " - + fact(new BigInteger("100"))); -} -\end{scalaprogram} - -\Scala's \code{import} statement looks very similar to \Java's -equivalent, but an important difference appears here: to import all -the names of a package or class, one uses the underscore (\verb|_|) -character instead of the asterisk (\verb|*|). That's because the -asterisk is actually a valid \Scala identifier, as we will see later. - -The \code{import} statement above therefore starts by importing the -class \code{BigInteger}, and then all the names it -contains. This makes the static fields \code{ZERO} and \code{ONE} -directly visible. - -While we're talking about \code{ZERO}, something must be said about -the condition of the \code{if} expression in method \code{fact}. Is -it really correct to check that \code{x} is zero by using the -\code{==} operator? A \Java programmer would say no, because in that -language the \code{==} operator compares objects by physical -equality, and this is not what we want here. What we want to know is -whether \code{x} is \emph{some} big integer object representing zero, -and there might be several of them. So a \Java programmer would use -the \code{equals} method to perform the comparison. - -The \Scala programmer, on the other hand, can use \code{==} here -because that operator compares objects according to the \code{equals} -method. Is \code{==} just an alias for \code{equals} then? Well, -almost, but \code{==} has one advantage over \code{equals} in that -it works also when the selector is the \code{null} constant. - -The \code{fact} method also shows some characteristics of \Scala's -syntax. The first one is that the method body does not have to be -surrounded by curly braces if it consists of a single expression. -The second one is that methods taking one argument can be used with an -infix syntax. That is, the expression -\begin{lstlisting} -x subtract ONE -\end{lstlisting} -is just another, slightly less verbose way of writing the expression -\begin{lstlisting} -x.subtract(ONE) -\end{lstlisting} -This might seem like a minor syntactic detail, but it has important -consequences, one of which will be explored in the next section. - -To conclude this section about integration with \Java, it should be -noted that it is also possible to inherit from \Java classes and -implement \Java interfaces directly in \Scala. - -\section{Everything is an object} -\label{sec:everything-an-object} - -\Scala is a pure object-oriented language in the sense that -\emph{everything} is an object, including numbers or functions. It -differs from \Java in that respect, since \Java distinguishes numeric -types from objects, and does not enable one to manipulate functions as -values. - -\subsection{Numbers are objects} -\label{sec:numbers-are-objects} - -Since numbers are objects, they also have methods. And in fact, an -arithmetic expression like the following: -\begin{lstlisting} -1 + 2 * 3 / x -\end{lstlisting} -consists exclusively of method calls, because it is equivalent to the -following expression, as we saw in the previous section: -\begin{lstlisting} -1.+(2.*(3./(x))) -\end{lstlisting} -This also means that \code{+}, \code{*}, etc. are valid identifiers -in \Scala. - -\subsection{Functions are objects} -\label{sec:funct-are-objects} - -Perhaps more surprising for the \Java programmer, functions are also -objects in \Scala. It is therefore possible to pass functions as -arguments, to store them in variables, and to return them from other -functions. This ability to manipulate functions as values is one of -the cornerstone of a very interesting programming paradigm called -\emph{functional programming}. - -As a very simple example of why it can be useful to use functions as -values, let's consider a timer function whose aim is to perform some -action every second. How do we pass it the action to perform? Quite -logically, as a function. This very simple kind of function passing -should be familiar to many programmers: it is often used in -user-interface code, to register call-back functions which get called -when some event occurs. - -In the following program, the timer function is called -\code{oncePerSecond}, and it gets a call-back function as argument. -The type of this function is written \verb|() => unit| and is the type -of all functions which have no arguments and return a value of type -\code{unit}. The main function of this program simply calls this -timer function with a call-back which prints a sentence on the -terminal. In other words, this program endlessly prints the sentence -\emph{time flies like an arrow} every second. -\begin{scalaprogram}{Timer} -object Timer { - def oncePerSecond(callback: () => unit): unit = - while (true) { callback(); Thread sleep 1000 }; - - def timeFlies(): unit = - Console.println("time flies like an arrow..."); - - def main(args: Array[String]): unit = - oncePerSecond(timeFlies); -} -\end{scalaprogram} -We note that in order to print the string, we used method -\code{println} of class \code{Console} instead of using the one from -\code{System.out}. For now, \code{Console} can be seen as a \Scala -equivalent of \Java's \code{System.out}. - -\subsubsection{Anonymous functions} -\label{sec:anonymous-functions} - -While this program is easy to understand, it can be refined a bit. -First of all, notice that the function \code{timeFlies} is only -defined in order to be passed later to the \code{oncePerSecond} -function. Having to name that function, which is only used once, might -seem unnecessary, and it would in fact be nice to be able to construct -this function just as it is passed to \code{oncePerSecond}. This is -possible in \Scala using \emph{anonymous functions}, which are exactly -that: functions without a name. The revised version of our timer -program using an anonymous function instead of \code{timeFlies} looks -like that: -\begin{scalaprogram}{TimerAnonymous} -object TimerAnonymous { - def oncePerSecond(callback: () => unit): unit = - while (true) { callback(); Thread sleep 1000 }; - - def main(args: Array[String]): unit = - oncePerSecond(() => - Console.println("time flies like an arrow...")); -} -\end{scalaprogram} -The presence of an anonymous function in this example is revealed by -the right arrow `\verb|=>|' which separates the function's argument -list from its body. In this example, the argument list is empty, as -witnessed by the empty pair of parenthesis on the left of the arrow. -The body of the function is the same as the one of \code{timeFlies} -above. - -% TODO fonctions avec environnement - -\section{Classes} -\label{sec:classes} - -As we have seen above, \Scala is an object-oriented language, and as -such it has a concept of class.\footnote{For the sake of completeness, - it should be noted that some object-oriented languages do not have - the concept of class, but \Scala is not one of them.} -Classes in \Scala are declared using a syntax which is close to -\Java's syntax. One important difference is that classes in \Scala can -have parameters. This is illustrated in the following definition of -complex numbers. -\begin{scalaprogram}{Complex} -class Complex(real: double, imaginary: double) { - def re() = real; - def im() = imaginary; -} -\end{scalaprogram} -This complex class takes two arguments, which are the real and -imaginary part of the complex. These arguments must be passed when -creating an instance of class \code{Complex}, as follows: \code{new - Complex(1.5, 2.3)}. The class contains two methods, called \code{re} -and \code{im}, which give access to these two parts. - -It should be noted that the return type of these two methods is not -given explicitly. It will be inferred automatically by the compiler, -which looks at the right-hand side of these methods and deduces that -both return a value of type \code{double}. - -The compiler is not always able to infer types like it does here, and -there is unfortunately no simple rule to know exactly when it will be, -and when not. In practice, this is usually not a problem since the -compiler complains when it is not able to infer a type which was not -given explicitly. As a simple rule, beginner \Scala programmers should -try to omit type declarations which seem to be easy to deduce from the -context, and see if the compiler agrees. After some time, the -programmer should get a good feeling about when to omit types, and -when to specify them explicitly. - -\subsection{Methods without arguments} -\label{sec:meth-wo-args} - -A small problem of the methods \code{re} and \code{im} is that, in -order to call them, one has to put an empty pair of parenthesis after -their name, as the following example shows: -\begin{lstlisting}[escapechar=\#] -val c = new Complex(1.2, 3.4); -Console.println("imaginary part: " + c.im()); -\end{lstlisting} -It would be nicer to be able to access the real and imaginary parts -like if they were fields, without putting the empty pair of -parenthesis. This is perfectly doable in \Scala, simply by defining -them as methods \emph{without arguments}. Such methods differ from -methods with zero arguments in that they don't have parenthesis after -their name, neither in their definition nor in their use. Our -\code{Complex} class can be rewritten as follows: -\begin{scalaprogram}{Complex2} -class Complex(real: double, imaginary: double) { - def re = real; - def im = imaginary; -} -\end{scalaprogram} - -\subsection{Inheritance and overriding} -\label{sec:inheritance} - -All classes in \Scala inherit from a super-class. When no super-class -is specified, as in the \code{Complex} example of previous section, -\code{scala.Object} is implicitly used. - -It is possible to override methods inherited from a super-class in -\Scala. It is however mandatory to explicitly specify that a method -overrides another one using the \code{override} modifier, in order to -avoid accidental overriding. As an example, our \code{Complex} class -can be augmented with a redefinition of the \code{toString} method -inherited from \code{Object}. -\begin{scalaprogram}{Complex3} -class Complex(real: double, imaginary: double) { - def re = real; - def im = imaginary; - override def toString() = - "" + re + (if (im < 0) "" else "+") + im + "i"; -} -\end{scalaprogram} - -\section{Case classes and pattern matching} -\label{sec:case-classes-pattern} - -A kind of data structure that often appears in programs is the tree. -For example, interpreters and compilers usually represent programs -internally as trees; XML documents are trees; and several kinds of -containers are based on trees, like red-black trees. - -We will now examine how such trees are represented and manipulated in -\Scala through a small calculator program. The aim of this program is -to manipulate very simple arithmetic expressions composed of sums, -integer constants and variables. Two examples of such expressions are -$1+2$ and $(x+x)+(7+y)$. - -We first have to decide on a representation for such expressions. The -most natural one is the tree, where nodes are operations (here, the -addition) and leaves are values (here constants or variables). - -In \Java, such a tree would be represented using an abstract -super-class for the trees, and one concrete sub-class per node or -leaf. In a functional programming language, one would use an algebraic -data-type for the same purpose. \Scala provides the concept of -\emph{case classes} which is somewhat in between the two. Here is how -they can be used to define the type of the trees for our example: -\beginscalaprogram{Calculator} -\begin{scalacode} -abstract class Tree; -case class Sum(l: Tree, r: Tree) extends Tree; -case class Var(n: String) extends Tree; -case class Const(v: int) extends Tree; -\end{scalacode} -The fact that classes \code{Sum}, \code{Var} and \code{Const} are -declared as case classes means that they differ from standard classes -in several respects: -\begin{itemize} -\item the \code{new} keyword is not mandatory to create instances of - these classes (i.e. one can write \code{Const(5)} instead of - \code{new Const(5)}), -\item getter functions are automatically defined for the constructor - parameters (i.e. it is possible to get the value of the \code{v} - constructor parameter of some instance \code{c} of class - \code{Const} just by writing \code{c.v}), -\item default definitions for methods \code{equals} and - \code{hashCode} are provided, which work on the \emph{structure} of - the instances and not on their identity, -\item a default definition for method \code{toString} is provided, and - prints the value in a ``source form'' (e.g. the tree for expression - $x+1$ prints as \code{Sum(Var(x),Const(1))}), -\item instances of these classes can be decomposed through - \emph{pattern matching} as we will see below. -\end{itemize} - -Now that we have defined the data-type to represent our arithmetic -expressions, we can start defining operations to manipulate them. We -will start with a function to evaluate an expression in some -\emph{environment}. The aim of the environment is to give values to -variables. For example, the expression $x+1$ evaluated in an -environment which associates the value $5$ to variable $x$, written -\{$x\rightarrow 5$\}, gives $6$ as result. - -We therefore have to find a way to represent environments. We could of -course use some associative data-structure like a hash table, but we -can also directly use functions! An environment is really nothing more -than a function which associates a value to a (variable) name. The -environment \{$x\rightarrow 5$\} given above can simply be written as -follows in \Scala: -\begin{lstlisting} - { case "x" => 5 } -\end{lstlisting} -This notation defines a function which, when given the string -\code{"x"} as argument, returns the integer 5, and fails with an -exception otherwise. - -Before writing the evaluation function, let us give a name to the type -of the environments. We could of course always use the type -\code{String => int} for environments, but it simplifies the program -if we introduce a name for this type, and makes future changes easier. -This is accomplished in \Scala with the following notation: -\begin{scalainvisiblecode} -object Calculator { -\end{scalainvisiblecode} -\begin{scalacode} - type Environment = (String => int); -\end{scalacode} -From then on, the type \code{Environment} can be used as an alias of -the type of functions from \code{String} to \code{int}. - -We can now give the definition of the evaluation function. -Conceptually, it is very simple: the value of a sum of two expressions -is simply the sum of the value of these expressions; the value of a -variable is obtained directly from the environment; and the value of a -constant is the constant itself. Expressing this in \Scala is not more -difficult: -\begin{scalacode} - def eval(t: Tree, env: Environment): int = t match { - case Sum(l, r) => eval(l, env) + eval(r, env) - case Var(n) => env(n) - case Const(v) => v - } -\end{scalacode} -This evaluation function works by performing \emph{pattern matching} -on the tree \code{t}. Intuitively, the meaning of the above definition -should be clear: -\begin{enumerate} -\item it first checks if the tree \code{t} is a \code{Sum}, and if it - is, it binds the left sub-tree to a new variable called \code{l} and - the right sub-tree to a variable called \code{r}, and then proceeds - with the evaluation of the expression following the arrow; this - expression can (and does) make use of the variables bound by the - pattern appearing on the left of the arrow, i.e. \code{l} and - \code{r}, -\item if the first check does not succeed, that is if the tree is not - a \code{Sum}, it goes on and checks if \code{t} is a \code{Var}; if - it is, it binds the name contained in the \code{Var} node to a - variable \code{n} and proceeds with the right-hand expression, -\item if the second check also fails, that is if \code{t} is neither a - \code{Sum} nor a \code{Var}, it checks if it is a \code{Const}, and - if it is, it binds the value contained in the \code{Const} node to a - variable \code{v} and proceeds with the right-hand side, -\item finally, if all checks fail, an exception is raised to signal - the failure of the pattern matching expression; this could happen - here only if more sub-classes of \code{Tree} were declared. -\end{enumerate} -We see that the basic idea of pattern matching is to attempt to match -a value to a series of patterns, and as soon as a pattern matches, -extract and name various parts of the value, to finally evaluate some -code which typically makes use of these named parts. - -A seasoned object-oriented programmer might wonder why we did not -define \code{eval} as a \emph{method} of class \code{Tree} and its -subclasses. We could have done it actually, since \Scala allows method -definitions in case classes just like in normal classes. Deciding -whether to use pattern matching or methods is therefore a matter of -taste, but it also has important implications on extensibility: -\begin{itemize} -\item when using methods, it is easy to add a new kind of node as this - can be done just by defining the sub-class of \code{Tree} for it; on - the other hand, adding a new operation to manipulate the tree is - tedious, as it requires modifications to all sub-classes of - \code{Tree}, -\item when using pattern matching, the situation is reversed: adding a - new kind of node requires the modification of all functions which do - pattern matching on the tree, to take the new node into account; on - the other hand, adding a new operation is easy, by just defining it - as an independent function. -\end{itemize} - -To explore pattern matching further, let us define another operation -on arithmetic expressions: symbolic derivation. The reader might -remember the following rules regarding this operation: -\begin{enumerate} -\item the derivative of a sum is the sum of the derivatives, -\item the derivative of some variable $v$ is one if $v$ is the - variable relative to which the derivation takes place, and zero - otherwise, -\item the derivative of a constant is zero. -\end{enumerate} -These rules can be translated almost literally into \Scala code, to -obtain the following definition: -\begin{scalacode} - def derive(t: Tree, v: String): Tree = t match { - case Sum(l, r) => Sum(derive(l, v), derive(r, v)) - case Var(n) if (v == n) => Const(1) - case _ => Const(0) - } -\end{scalacode} -This function introduces two new concepts related to pattern matching. -First of all, the \code{case} expression for variables has a -\emph{guard}, an expression following the \code{if} keyword. This -guard prevents pattern matching from succeeding unless its expression -is true. Here it is used to make sure that we return the constant 1 -only if the name of the variable being derived is the same as the -derivation variable \code{v}. The second new feature of pattern -matching used here is the \emph{wild-card}, written \code{_}, which is -a pattern matching any value, without giving it a name. - -We did not explore the whole power of pattern matching yet, but we -will stop here in order to keep this document short. We still want to -see how the two functions above perform on a real example. For that -purpose, let's write a simple \code{main} function which performs -several operations on the expression $(x+x)+(7+y)$: it first computes -its value in the environment $\{x\rightarrow 5, y\rightarrow 7\}$, then -computes its derivative relative to $x$ and then $y$. -\begin{scalacode} - def main(args: Array[String]): Unit = { - val exp: Tree = Sum(Sum(Var("x"),Var("x")),Sum(Const(7),Var("y"))); - val env: Environment = { case "x" => 5 case "y" => 7 }; - Console.println("Expression: " + exp); - Console.println("Evaluation with x=5, y=7: " + eval(exp, env)); - Console.println("Derivative relative to x:\n " + derive(exp, "x")); - Console.println("Derivative relative to y:\n " + derive(exp, "y")); - } -\end{scalacode} -\begin{scalainvisiblecode} -} // object Calculator -\end{scalainvisiblecode} -\endscalaprogram{Calculator} -Executing this program, we get the expected output: -\scalaprogramoutput{Calculator} -By examining the output, we see that the result of the derivative -should be simplified before being presented to the user. Defining a -basic simplification function using pattern matching is an interesting -(but surprisingly tricky) problem, left as an exercise for the reader. - -\section{Mixins} -\label{sec:mixins} - -Apart from inheriting code from a super-class, a \Scala class can also -import code from one or several \emph{mixins}. - -Maybe the easiest way for a \Java programmer to understand what mixins -are is to view them as interfaces which can also contain code. In -\Scala, when a class inherits from a mixin, it implements that mixin's -interface, and inherits all the code contained in the mixin. - -To see the usefulness of mixins, let's look at a classical example: -ordered objects. It is often useful to be able to compare objects of a -given class among themselves, for example to sort them. In \Java, -objects which are comparable implement the \code{Comparable} -interface. In \Scala, we can do a bit better than in \Java by defining -our equivalent of \code{Comparable} as a mixin, which we will call -\code{Ord}. - -When comparing objects, six different predicates can be useful: -smaller, smaller or equal, equal, not equal, greater or equal, and -greater. However, defining all of them is fastidious, especially since -four out of these six can be expressed using the remaining two. That -is, given the equal and smaller predicates (for example), one can -express the other ones. In \Scala, all these observations can be -nicely captured by the following mixin declaration: -\beginscalaprogram{Ord} -\begin{scalacode} -abstract class Ord { - def < (that: Any): boolean; - def <=(that: Any): boolean = (this < that) || (this == that); - def > (that: Any): boolean = !(this <= that); - def >=(that: Any): boolean = !(this < that); -} -\end{scalacode} -This definition both creates a new type called \code{Ord}, which -plays the same role as \Java's \code{Comparable} interface, and -default implementations of three predicates in terms of a fourth, -abstract one. The predicates for equality and inequality do not appear -here since they are by default present in all objects. - -The type \code{Any} which is used above is the type which is a -super-type of all other types in \Scala. It can be seen as a more -general version of \Java's \code{Object} type, since it is also a -super-type of basic types like \code{int}, \code{float}, etc. - -To make objects of a class comparable, it is therefore sufficient to -define the predicates which test equality and inferiority, and mix in -the \code{Ord} class above. As an example, let's define a -\code{Date} class representing dates in the Gregorian calendar. Such -dates are composed of a day, a month and a year, which we will all -represent as integers. We therefore start the definition of the -\code{Date} class as follows: -\begin{scalacode} -class Date(y: int, m: int, d: int) with Ord { - def year = y; - def month = m; - def day = d; - - override def toString(): String = year + "-" + month + "-" + day; -\end{scalacode} -The important part here is the \code{with Ord} declaration which -follows the class name and parameters. It declares that the -\code{Date} class inherits from the \code{Ord} class as a mixin. - -Then, we redefine the \code{equals} method, inherited from -\code{Object}, so that it correctly compares dates by comparing their -individual fields. The default implementation of \code{equals} is not -usable, because as in \Java it compares object physically. We arrive -at the following definition: -\begin{scalacode} - override def equals(that: Any): boolean = { - that.isInstanceOf[Date] && { - val o = that.asInstanceOf[Date]; - o.day == day && o.month == month && o.year == year - } - } -\end{scalacode} -This method makes use of the predefined methods \code{isInstanceOf} -and \code{asInstanceOf}. The first one, \code{isInstanceOf}, -corresponds to \Java's \code{instanceof} operator, and returns true -if and only if the object on which it is applied is an instance of the -given type. The second one, \code{asInstanceOf}, corresponds to -\Java's cast operator: If the object is an instance of the given type, -it is viewed as such, otherwise a \code{ClassCastException} is -thrown. - -Finally, the last method to define is the predicate which tests for -inferiority, as follows. It makes use of another predefined method, -\code{error}, which throws an exception with the given error message. -\begin{scalacode} - def <(that: Any): boolean = { - if (!that.isInstanceOf[Date]) - error("cannot compare " + that + " and a Date"); - - val o = that.asInstanceOf[Date]; - (year < o.year) - || (year == o.year && (month < o.month - || (month == o.month && day < o.day))) - } -} -\end{scalacode} -\endscalaprogram{Ord} -This completes the definition of the \code{Date} class. Instances of -this class can be seen either as dates or as comparable objects. -Moreover, they all define the six comparison predicates mentioned -above: \code{equals} and \code{<} because they appear directly in -the definition of the \code{Date} class, and the others because they -are inherited from the \code{Ord} mixin. - -Mixins are useful in other situations than the one shown here, of -course, but discussing their applications in length is outside the -scope of this document. - -\section{Genericity} -\label{sec:genericity} - -The last characteristic of \Scala we will explore in this tutorial is -genericity. \Java programmers should be well aware of the problems -posed by the lack of genericity in their language, a shortcoming which -is addressed in \Java 1.5. - -Genericity is the ability to write code parametrised by types. For -example, a programmer writing a library for linked lists faces the -problem of deciding which type to give to the elements of the list. -Since this list is meant to be used in many different contexts, it is -not possible to decide that the type of the elements has to be, say, -\code{int}. This would be completely arbitrary and overly -restrictive. - -\Java programmers resort to using \code{Object}, which is the -super-type of all objects. This solution is however far from being -ideal, since it doesn't work for basic types (\code{int}, -\code{long}, \code{float}, etc.) and it implies that a lot of -dynamic type casts have to be inserted by the programmer. - -\Scala makes it possible to define generic classes (and methods) to -solve this problem. Let us examine this with an example of the -simplest container class possible: a reference, which can either be -empty or point to an object of some type. -\beginscalaprogram{Reference} -\begin{scalacode} -class Reference[a] { - private var contents: a = _; - - def set(value: a): Unit = { contents = value; } - def get: a = contents; -} -\end{scalacode} -The class \code{Reference} is parametrised by a type, called \code{a}, -which is the type of its element. This type is used in the body of the -class as the type of the \code{contents} variable, the argument of -the \code{set} method, and the return type of the \code{get} method. - -The above code sample introduces variables in \Scala, which should not -require further explanations. It is however interesting to see that -the initial value given to that variable is \code{_}, which represents -a default value. This default value is 0 for numeric types, -\code{false} for the boolean type, \code{()} for the unit type and -\code{null} for all object types. - -To use this \code{Reference} class, one needs to specify which type to use -for the type parameter \code{a}, that is the type of the element -contained by the cell. For example, to create and use a cell holding -an integer, one could write the following: -\begin{scalacode} -object IntegerReference { - def main(args: Array[String]): Unit = { - val cell = new Reference[Int]; - cell.set(13); - Console.print("Reference contains the half of " + (cell.get * 2)); - } -} -\end{scalacode} -\endscalaprogram{Reference} -As can be seen in that example, it is not necessary to cast the value -returned by the \code{get} method before using it as an integer. It -is also not possible to store anything but an integer in that -particular cell, since it was declared as holding an integer. - -\section{Conclusion} -\label{sec:conclusion} - -This document gave a quick overview of the \Scala language and -presented some basic examples. The interested reader can go on by -reading the companion document \textit{Scala By Example\/}, which -contains much more advanced examples, and consult the \textit{Scala - Language Specification\/} when needed. - -\end{document} - -% LocalWords: mixins mixin mixin's genericity |