《Scala Tutorial 中文版》 草稿





A Scala Tutorial

for Java  programmers

Version 1.3

March 15, 2009

Michel Schinz, Philipp


Translated to Simplified Chinese by Bearice




1    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.


2    A first example 第一个例子

As a first example, we will use the standard Hello world program. It is not very fasci- nating but  makes it easy to demonstrate the use of the Scala tools without knowing too much about the language. Here is how it looks:

作为学习Scala的第一部,我们将首先写一个标准的HelloWorld,这个虽然不是很有趣,但是它可以是你对Scala有一个最直观的认识而不需要太多关于这个语言的知识。我们的Hello world看起来像这样:

object HelloWorld {

def main(args: Array[String]) {

println(“Hello, world!”)



The structure of this  program should be familiar to Java programmers: it consists of one  method called 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  pre- defined method println with the friendly greeting as argument. The main method does  not  return a value (it is a procedure method). Therefore, it is not  necessary to declare a return type.

程序的结构对Java程序员来说可能很令人怀念:它由一个main函数来接受命令行参数,也就是一个String数组。这个函数的唯一一行代码把我们的问候语传递给了一个叫println的预定义函数。main函数不返回值(所以它是一个procedure method)。所以,也不需要声明返回类型。

What  is less familiar to Java programmers is the  object declaration containing the main method. Such  a declaration introduces what  is commonly known as a single- ton object, that is a class with a single instance. The declaration above thus declares both a class called HelloWorld and  an instance of that class, also called HelloWorld. This instance is created on demand, the first time  it is used.


The astute reader might have noticed that the main method is not declared as 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.


2.1   Compiling the 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.

我们使用Scala编译器“scalac”来编译Scala代码。和大多数编译器一样,scalac 接受源文件名和一些选项作为参数,生成一个或者多个目标文件。scala编译生成的产物就是标准的Java类文件。

If we save  the  above program in a file called HelloWorld.scala, we can  compile it by issuing the  following command (the  greater-than sign ‘>’ represents the  shell prompt and  should not be typed):


2.2    Running  the example                                                                                                                           3

> scalac HelloWorld.scala

This will generate a few class files in the current directory. One of them will be called HelloWorld.class, and  contains a class  which can  be directly executed using the scala command, as the following section shows.

这将会在当前目录生成一系列.class文件。其中的一个名为HelloWorld.class 的文件中定义了一个可以直接使用scala命令执行的类。下文中你可以看到这个例子。

2.2   Running  the 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:


> scala -classpath . HelloWorld

Hello, world!

3    Interaction with Java Java交互

One  of Scala’s strengths is that it makes it very easy to interact with  Java code. All classes from  the  java.lang package are imported by default, while  others need to be imported explicitly.


Let’s look at an example that demonstrates this.  We want to obtain and  format the current date according to the conventions used in a specific country, say France1 .


Java’s class  libraries define powerful utility  classes, such as Date and  DateFormat. Since Scala interoperates seemlessly with Java, there is no need to implement equiv- alent classes in the Scala class library–we can  simply import the  classes of the  cor- responding Java packages:


import java.util.{Date, Locale} import java.text.DateFormat import java.text.DateFormat._

object FrenchDate {

def main(args: Array[String]) {

val now = new Date

val df = getDateInstance(LONG, Locale.FRANCE)

println(df format now)



1 Other regions such as the french speaking part of Switzerland use the same conventions.



Scala’s import statement looks very similar to Java’s equivalent, however, it is more powerful.  Multiple classes can  be imported from  the  same package by enclosing them in curly braces as on the first line.  Another difference is that when importing all the names of a package or class, one uses the underscore character (_) instead of the  asterisk (*).  That’s because the  asterisk is a valid Scala identifier (e.g.  method name), as we will see later.


The import statement on the third line therefore imports all members of the DateFormat class.  This makes the  static method getDateInstance and  the  static field LONG di- rectly visible.


Inside the  main method we first  create an  instance of Java’s Date class  which by default contains the  current date.  Next,  we define a date format using the  static getDateInstance method that we imported previously. Finally, we print the current date formatted according to the localized DateFormat instance. This last line shows an interesting property of Scala’s syntax.  Methods taking one argument can be used with an infix syntax. That is, the expression


df format now

is just another, slightly less verbose way of writing the expression



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.


4    Everything is an object 万物皆对象

Scala  is a pure object-oriented language in the  sense that everything is an  object, including numbers or functions. It differs  from  Java in that respect, since  Java dis- tinguishes primitive types (such as boolean and int) from reference types, and does not enable one to manipulate functions as values.


4.1   Numbers are objects 数字和对象

Since  numbers are objects, they  also have  methods. And in fact, an arithmetic ex- pression like the following:


1 + 2 * 3 / x

consists exclusively of method calls, because it is equivalent to the following expres- sion, as we saw in the previous section:


4.2    Functions are objects                                                                                                                              5


This also means that +, *, etc. are valid identifiers in Scala.

这也意味着 +,-,*,/ 在Scala中也是有效的名称。

The parentheses around the numbers in the second version are necessary because Scala’s lexer uses  a longest match rule for tokens. Therefore, it would break the fol- lowing expression:



into the tokens 1., +, and 2. The reason that this tokenization is chosen is because 1. is a longer valid match than 1. The token 1. is interpreted as the literal  1.0, making it a Double rather than an Int. Writing the expression as:

理解成表达项 1. ,+,和2的组合。这样的组合结果是由于1.是一个有效的表达项并且比表达项1要长,表达项1.会被当作1.0 ,使得它成为一个double而不是int。而下面的表达式阻止了分析器错误的理解


prevents 1 from being interpreted as a Double.

4.2   Functions 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 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  oncePerSecond, and  it gets a call-back function as argument. The type  of this  function is written () => Unit and  is the  type  of all functions which take  no  arguments and  return nothing (the type  Unit is similar to void in C/C++).  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 “time  flies like an arrow” every second.

在下面的程序中,计时器函数被叫做oncePerSceond,它接受一个回调函数作为参数。这种函数的类型被写作 () => Unit ,他们不接受任何参数也没有任何返回(Unit关键字类似于C/C++中的void)。程序的主函数调用计时器并传递一个打印某个句子的函数作为回调。换句话说,这个程序永无止境的每秒打印一个“time  flies like an arrow”。

object Timer {

def oncePerSecond(callback: () => Unit) {

while (true) { callback(); Thread sleep 1000 }


def timeFlies() {

println(“time flies like an arrow…”)



def main(args: Array[String]) {




Note  that in order to print the  string, we used the  predefined method println in- stead of using the one from System.out.


4.2.1  Anonymous functions 匿名函数

While this  program is easy  to understand, it can  be refined a bit.   First  of all, no- tice  that the  function timeFlies is only  defined in order to be passed later  to the 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 oncePerSecond. This is possible in Scala using  anony- mous functions, which are exactly that: functions without a name. The revised ver- sion of our timer program using an anonymous function instead of timeFlies looks like that:


object TimerAnonymous {

def oncePerSecond(callback: () => Unit) {

while (true) { callback(); Thread sleep 1000 }


def main(args: Array[String]) {

oncePerSecond(() =>

println(“time flies like an arrow…”))



The presence of an anonymous function in this example is revealed by the right ar- row ‘=>’ 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 timeFlies above.


5    Classes

As we have  seen  above, Scala is an  object-oriented language, and  as such it has  a concept of class.2 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.


class Complex(real: Double, imaginary: Double) {

2 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.


5.1    Methods without arguments                                                                                                                  7

def re() = real

def im() = imaginary


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  Complex, as follows:  new Complex(1.5, 2.3).  The  class  contains two meth- ods, called re and  im, which give access to these two parts.

我们的复数类(Complex)接受两个参数:实部和虚部。这些参数必须在实例化时进行传递,就像这样:new Complex(1.5, 2.3)。类定义中包括两个叫做re和im的方法,分别接受上面提到的两个参数。

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 Double.


The compiler is not always able to infer types  like it does here, and  there is unfortu- nately 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 con- text, 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.


5.1   Methods without  arguments 无参方法。

A small  problem of the  methods re and  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:


object ComplexNumbers {

def main(args: Array[String]) {

val c = new Complex(1.2, 3.4)

println(“imaginary part: ” + c.im())



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 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 Complex class can be rewritten as follows:


class Complex(real: Double, imaginary: Double) {

def re = real

def im = imaginary



5.2   Inheritance and overriding 继承和覆盖

All classes in Scala inherit from  a super-class. When  no super-class is specified, as in the Complex example of previous section, scala.AnyRef is implicitly used.


It is possible to override methods inherited from  a super-class in Scala.  It is how- ever mandatory to explicitly specify  that a method overrides another one  using the override modifier, in  order to  avoid  accidental overriding.  As an  example, our Complex class can be augmented with a redefinition of the toString method inher- ited from Object.


class Complex(real: Double, imaginary: Double) {

def re = real

def im = imaginary

override def toString() =

“” + re + (if (im < 0) “” else “+”) + im + “i”


6    Case classes and pattern  matching 条件类和模式匹配

A kind of data structure that often appears in programs is the tree.  For example, in- terpreters and  compilers usually represent programs internally as trees;  XML doc- uments 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 ).

接下来我们将通过一个计算器程序来研究树在Scala中是如何表示和操纵的。这个程序的目标是处理一些由整数常量、变量和加号组成的简单的算数表达式,例如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 con- cept  of 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:

在Java中,这样的树可以表示为一个超类的树的集合,节点由不同子类的实例表示。而在函数式语言中,我们可以使用代数类型(algebraic data-type)来达到同样的目的。Scala提供了一种介于两者之间的叫做条件类(Case Classes)的东西。

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

The fact that classes Sum, Var and Const are declared as case classes means that they differ from standard classes in several respects:

我们实际上定义了三个条件类 Sum ,Var 和 Const 。这些类和普通类有若干不同:

6  Case classes and pattern matching                                                                                                            9

•  the new keyword is not mandatory to create instances of these classes (i.e. one can write Const(5) instead of new Const(5)),

实例化时可以省略new关键字(例如你可以使用 Const(5)而不必使用 new Const(5) )

•  getter functions are automatically defined for the constructor parameters (i.e. it is possible to get the value of the v constructor parameter of some instance c of class Const just by writing c.v),


•  default definitions for methods equals and hashCode are provided, which work on the structure of the instances and  not on their  identity,


•  a default definition for method toString is provided, and prints the value in a

“source form” (e.g. the tree for expression x +1 prints as Sum(Var(x),Const(1))),


•  instances of these classes can  be decomposed through pattern matching as we will see below.


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 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 → 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 → 5} given  above can  simply be written as follows in Scala:

这样一来我们需要找到一个表示这种绑定关系的方法。当然我们可以使用某种类似hash-table的数据结构,不过我们也可以直接使用函数!一个上下文无非就是一个吧名称映射到值的函数。例如上面给出的{x → 5}的这个映射我们就可以在Scala中表示为:

{ case “x” => 5 }

This notation defines a function which, when given the string “x” as argument, re- turns the integer 5, and  fails with an exception otherwise.

这个定义了一个函数:当参数等于字符串”x” 时返回整数5,否则抛出异常。

Before writing the evaluation function, let us give a name to the type of the environ- ments. We could of course always  use  the  type  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:


type Environment = String => Int

From  then on, the type Environment can be used as an alias of the type of functions from String to 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:


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


This evaluation function works by performing pattern matching on the tree t. Intu- itively, the meaning of the above definition should be clear:


  1. it first checks if the tree t is a Sum, and  if it is, it binds the left sub-tree to a new variable called  l and  the  right  sub-tree to a variable called  r, and  then pro- ceeds with the  evaluation of the  expression following the  arrow;  this  expres- sion can (and does) make use of the variables bound by the pattern appearing on the left of the arrow, i.e. l and  r,


  1. if the first check  does not succeed, that is if the tree is not a Sum, it goes on and checks if t is a Var; if it is, it binds the  name contained in the  Var node to a variable n and  proceeds with the right-hand expression,


  1. if the  second check  also fails, that is if t is neither a Sum nor  a Var, it checks if it is a Const, and  if it is, it binds the value  contained in the  Const node to a variable v and  proceeds with the right-hand side,


  1. finally, if all checks fail, an exception is raised to signal  the failure of the  pat- tern matching expression; this could happen here  only if more sub-classes of Tree were declared.


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 eval as a method of class 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:


•  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 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 Tree,


•  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.


6  Case classes and pattern matching                                                                                                         11

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:


  1. the derivative of a sum  is the sum  of the derivatives,


  1. the derivative of some variable v is one if v is the variable relative to which the derivation takes place, and  zero otherwise,


  1. the derivative of a constant is zero.


These rules can be translated almost literally into Scala code, to obtain the following definition:


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)


This function introduces two new concepts related to pattern matching. First of all, the  case expression for variables has  a guard,  an  expression following the  if key- word.  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 v. The second new feature of pattern matching used here  is the wild-card, written _, which is a pattern matching any value, without giving it a name.

这个函数使用了两个关于模式匹配的功能,首先case语句可以拥有一个guard子句:一个if条件表达式。除非guard的条件成立,否则该模式不会成功匹配。其次是通配符:_ 。这个模式表示和所有值匹配而不对任何变量赋值。

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 main func- tion  which performs several operations on  the  expression (x + x ) + (7 + y ): it first computes its value in the environment {x → 5, y → 7}, then computes its derivative relative to x and  then y .

事实上我们还远没有触及模式匹配的全部精髓。但是我们限于篇幅原因不得不再此停笔了。下面我们看看这个两个函数是如何在一个实例上运行的。为了达到这个目前我们写了一个简单的main函数来对表达式(x + x ) + (7 + y )进行若干操作:首先计算当{x → 5, y → 7}时表达式的值,然后分别对x和y求导。

def main(args: Array[String]) {

val exp: Tree = Sum(Sum(Var(“x”),Var(“x”)),Sum(Const(7),Var(“y”))) val env: Environment = { case “x” => 5 case “y” => 7 } println(“Expression: ” + exp)

println(“Evaluation with x=5, y=7: ” + eval(exp, env))

println(“Derivative relative to x:\n ” + derive(exp, “x”))

println(“Derivative relative to y:\n ” + derive(exp, “y”))


Executing this program, we get the expected output:


Expression: Sum(Sum(Var(x),Var(x)),Sum(Const(7),Var(y))) Evaluation with x=5, y=7: 24


Derivative relative to x: Sum(Sum(Const(1),Const(1)),Sum(Const(0),Const(0)))

Derivative relative to y: Sum(Sum(Const(0),Const(0)),Sum(Const(0),Const(1)))

By examining the  output, we see  that the  result of the  derivative should be  sim- plified  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.


7    Traits

Apart  from  inheriting code  from  a super-class, a Scala  class  can  also  import code from one or several traits.


Maybe  the  easiest way for a Java programmer to understand what  traitss are  is to view them as interfaces which can also contain code. In Scala, when a class inherits from a trait,  it implements that traits’s interface, and  inherits all the code  contained in the trait.


To see the  usefulness of traits, 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 Comparable interface. In Scala, we can  do a bit better than in Java by defining our equivalent of Comparable as a trait,  which we will call Ord.

让我们通过一个典型的实例来看看这种trait机制是如何发挥作用的:排序对象。能够比较若干给定类型的对象在实际应用中是很有用的,比如在进行排序时。在Java语言中可以比较的对象是通过实现Comparable接口完成的 。在Scala中我们可以通过吧Comparable定义为trait来做的比Java好一些。我们吧这个trait叫做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 trait  declaration:


trait 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)


This  definition both creates a new  type  called  Ord, which plays  the  same role  as Java’s 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.

这个定义在建立了一个叫做与Java中的 Comparable 等效的叫做 Ord的类型的同时还实现了使用抽象的一种关系推导其他三种的接口。比较相等性的方法没有出现是由于他已经默认存在于所有对象中了。

The type 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 Object type,  since  it is

7  Traits                                                                                                                                                                13

also a super-type of basic  types  like Int, Float, etc.


To make objects of a class comparable, it is therefore sufficient to define the predi- cates which test equality and inferiority, and mix in the Ord class above. As an exam- ple, let’s define a 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 Date class as follows:


class Date(y: Int, m: Int, d: Int) extends Ord {

def year = y def month = m def day = d

override def toString(): String = year + “-” + month + “-” + day

The important part here is the extends Ord declaration which follows the class name and  parameters. It declares that the Date class inherits from the Ord trait.

注意在类名后出现的extends Ord。这表示了这个类继承了Ord这个trait。

Then, we redefine the  equals method, inherited from  Object, so that it correctly compares dates by comparing their  individual fields.  The default implementation of equals is not usable, because as in Java it compares objects physically. We arrive at the following definition:


override def equals(that: Any): Boolean =

that.isInstanceOf[Date] && {

val o = that.asInstanceOf[Date]

o.day == day && o.month == month && o.year == year


This method makes use of the predefined methods isInstanceOf and asInstanceOf. The first one, isInstanceOf, corresponds to Java’s 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,  asInstanceOf, corresponds to Java’s cast  operator: if the  object is an instance of the given type, it is viewed  as such, otherwise a ClassCastException is thrown.

这个函数使用了预定义函数 isInstanceOf 和asInstanceOf 。第一个isInstanceOf 类似Java中的 instanceof :当且仅当对象是给定类型的实例时才返回true。第二个 asInstanceOf 对应Java中的类型转换操作:当对象是给定类型的子类时转换,否则抛出ClassCastException。

Finally,  the  last method to define is the  predicate which tests  for inferiority, as fol- lows. It makes use of another predefined method, error, which throws an exception with the given error message.

最后我们还需要定义测试小于关系的函数,如下面所示。这个函数使用了预定义的函数error ,它可以使用给定字符串抛出一个异常。

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)))



This completes the  definition of the  Date class.  Instances of this  class can  be seen either as dates or as comparable objects. Moreover, they all define the six compari- son predicates mentioned above: equals and  < because they appear directly in the definition of the Date class, and  the others because they are inherited from  the Ord trait.

以上就是Data的完整定义了。这个类的实例既可以作为日期显示,也可以进行比较。而且他们都定义了6种比较操作:其中两种 : equals和< 是我们直接定义的,而其他的是从Ord中继承的。

Traits  are  useful in other situations than the  one  shown here, of course, but  dis- cussing their applications in length is outside the scope of this document.

Traits  的应用远不止于此,不过更加深入的讨论不再本文的讨论范围内。

8    Genericity 泛型

The last characteristic of Scala we will explore in this tutorial is genericity. Java pro- grammers 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  parametrized by types. For example, a pro- grammer 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 differ- ent contexts, it is not possible to decide that the type of the elements has to be, say, Int. This would be completely arbitrary and  overly restrictive.


Java programmers resort to using 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  (int, long, 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  prob- lem. 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.


class Reference[T] {

private var contents: T = _

def set(value: T) { contents = value }

def get: T = contents


The class Reference is parametrized by a type,  called  T, which is the type of its ele- ment. This type is used in the body of the class as the type of the contents variable, the argument of the set method, and  the return type of the get method.


The above code  sample introduces variables in Scala, which should not require fur- ther  explanations. It is however interesting to see that the initial value given to that variable is _, which represents a default value.   This default value  is 0 for numeric types,  false for the Boolean type, () for the Unit type and  null for all object types.

上面的代码还演示了Scala中变量的表达方式,这个无需更多的解释大家都能清楚。不过值得注意的是我们给他赋予的初始值_ ,这个表示一个默认值,对于数字类型来说是0,对于boolean来说是false,对于Unit(函数签名)来说是() (无参数无返回),对于其他来说是null。

9  Conclusion                                                                                                                                                      15

To use this Reference class, one  needs to specify  which type to use for the type pa- rameter T, 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:

要使用这个Reference 类,你需要制定他的类型参数,来告知这个引用到底引用了什么类型。例如要创建一个指向Int的引用,你可以这么写:

object IntegerReference {

def main(args: Array[String]) {

val cell = new Reference[Int] cell.set(13)

println(“Reference contains the half of ” + (cell.get * 2))



As can be seen in that example, it is not necessary to cast the value returned by the 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.


9    Conclusion 结语

This document gave a quick overview of the Scala language and presented some ba- sic examples. The interested reader can go on by reading the companion document Scala By Example, which contains much more advanced examples, and  consult the Scala Language Specification when needed.

本文简要介绍了Scala语言的一些特性,并且同时展示了若干实例。有兴趣的读者可以继续阅读本文的姊妹篇:《Scala By Example》,该文覆盖了Scala的更多的高级特性。如果需要还可以去阅读《Scala Language Specification》。

>_<|| 我手贱!!这个有问题!绝对有问题!!一般般啦,真的很一般般。还不错哦~小表扬一下!GJ!乃就是新世界的神様了,快去拯救世界吧! (1 votes, average: 1.00 out of 5)

2 人次吐槽

  1. liang3404814说道:
    骑着 Opera Mini 4.2.13337 Opera Mini 4.2.13337 和 J2ME/MIDP Device J2ME/MIDP Device
    Opera/9.60 (J2ME/MIDP; Opera Mini/4.2.13337/504; U; ja) Presto/2.2.0


  2. ssword说道:
    骑着 Google Chrome Google Chrome 和 Windows XP Windows XP
    Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/530.5 (KHTML, like Gecko) Chrome/ Safari/530.5

    支持下 ^_^