In Scala, we do this by defining a class :

class Rational(x:Int, y:Int){
	def numer = x;
	def denom = y


This definition introduces two entitiles:

  • A new type, name Rational.

  • A constructor Rational to create elements of this type.

Scala keeps the names of types and values in different namespaces

So there’s no confict between the two definitions of Rational


We call the elements of a class type objects.

We create an object by prefixing an application of the constructor of the class with the operator new.

  • Example:

new Rational(1,2)

Members of an Object

Objects of the class Rational have two members, numer and denom.

We select the members of an object with the infix operator’.’(like in Java).

  • Example

val x = new Rational(1,2)                 //> x  : week3.Rational = week3.Rational@2c641e9a
x.numer                                         //> res0: Int = 1
x.denom                                         //> res1: Int = 2


One can go further and also package functions operating on a data abstraction in the data abstraction itself.

Such functions are called methods.

  • Example

Rational numbers now would have, in addition to the functions numer and denom, the functions add,sub,mul,div,equal,toString

class Rational(x:Int, y:Int){

	def numer = x
	def denom = y

	def add(that:Rational) = new Rational(numer*that.denom + denom*that.numer,
	 def neg:Rational = new Rational(-numer,denom)
	 def sub(that:Rational) = add(that.neg)
	 override def toString = numer + "/" + denom

2-6: More Fun With Rationals

###Rationals with Data Abstraction

class Rational(x:Int, y:Int){

	def numer = x/g
	def denom = y/g
	private def gcd(a:Int, b:Int) : Int = if (b == 0) a else gcd(b,a%b)
	private val g = gcd(x,y)


It is equally possible to turn number and denom into vals, so that they are computed only once:

class Rational(x:Int, y:Int){

	val numer = x/gcd(x,y)
	val denom = y/gcd(x,y)

这种优化和改动都在这个类的里面,并不影响调用者,这种对数据的封装成为data abstraction

Self Reference

On the inside of a class, the name this represents the object on which the current method is executed.

  • Example:

class Rational(x:Int, y:Int){


def less(that:Rational) = numer * that.denom < that.numer * denom

def max(that:Rational) = if(this.less(that)) that else this




class Rational(x:Int, y:Int){

	require(y != 0, "denominator can not be 0")


require is a predefined function.

It takes a condition and an optional message string.

if the condition is false than IllegalArgumentException is thrown with the given message string.


Besides require, there is also assert

Assert also takes a condition and an optional message:

val x = sqrt(y)
assert(x >= 0)



  • require is used to enforce a precondition on the caller of a function.

  • assert is used as to check the code of the function itself.



class Rational(x:Int, y:Int){

	 require(y != 0, "denominator can not be 0")

	 def this(x: Int) = this (x,1)


val z = new Rational(3)

2-7: Evaluations and Operations

Classes and Substitutions

我们之前可以使用substitution规则去分析函数,这节将这个规则用于class object

  • Question: How is an instantiation of the class new C(e1,...,em)

  • Answer: The expression arguments e1,...,em 参数和函数函数一样求值,得到:new C(v1,...,vm)


class C(x1,...,xm){ ... def f(y1,...,yn) = b ...}


  • 类的构造函数入参为:x1,...,xn

  • 类中定义个了一个函数f,参数为y1,...,yn

  • Question: How is the following expression evaluated?

new C(v1,...,vm).f(w1,...,wn)


上面的例子中,求两个有理数的和,代码为x.add(y),这种没有x + y 直观,因此,scala提供一种方式使方法调用变的更直观:


  • Step1: Infix Notation:

Any method with a parameter can be used like an infix operator.

it is therefore possible to write:

r add s  	=> 		r.add(s)

r less s 	=> 		r.less(s)

r max s		=>		r.max(s)

  • Step2: 定义操作符


 def < (that:Rational) = numer * that.denom < that.numer * denom


x.less(y)  等价于 x < y

2-8: Class Hierarchies

Abstract Classes

Consider the task of writing a class for sets of integers with the following operations


abstract class IntSet{

	def incl(x:Int):InSet
	def contains(x:Int):Boolean



IntSet is an abstract class.

抽象类可以定义接口,但不需要实现。 抽象类不可以直接用new创建

Class Extensions

Let’s consider implementing sets as binary trees.

There are two types of possible trees: a tree for the empty set, and a tree consisting of an integer and two sub-trees.

Here are their implementations

class Empty extends IntSet
	def contains(x:Int):Boolean = false
	def incl(x:Int):IntSet = new NonEmpty(x,new Empty, new Empty)


class NonEmpty(elem: Int, left: IntSet, right:IntSet) extends IntSet
	def contains(x:Int):Boolean = 
		if (x<elem) left.contains(x)
		else if (x>elem) right.contains(x)
		else true

	def incl(x:Int):IntSet = 
		if(x<elem) new NonEmpty(elem,left.incl(x), right)
		else if(x>elem) new NonEmpty(elem, left, right.incl(x))
		else this


###Base Classes and SubClasses

  • IntSet is called the superclass of Empty and NonEmpty.

  • Empty and NonEmpty are subclasses of IntSet.

  • In Scala, any user-defined class extends another class.

  • If no superclass is given , the standard class object in the Java package java.lang is assumed

  • The direct or indirect superclasses of a class C are called baseclasses of C

  • So, the base classes of NonEmpty are IntSet and Object

Implementing and Overriding


abstract class Base
	def foo = 1
	def bar:Int

class Sub extends Base
	override def foo = 2
	def bar = 3


Object Definitions


object class Empty extends IntSet
	def contains(x:Int):Boolean = false
	def incl(x:Int):IntSet = new NonEmpty(x,Empty,Empty)
	override def toString = {"."}


  • This defines a singleton object named Empty.

  • No other Empty instances can be created.

  • Singleton objects are valeus , so Empty evaluates to itself


之前的代码都是使用REPL或workSheet运行,这一节将会创建一个Scala Object:

package week4

object week4 {

  def main(args:Array[String]) = println("hello")

Dynamic Binding

Object-oriented languages(including Scala) implement dynmaic method dispatch.

This means that the code invoked by a method call depends on the runtime type of the object that contains the method.

  • Example

Empty contains 1

-> [1/x][Empty/this] false

= false

Something to Ponder

Dynamic dispatch of methods is analogous to calls to higher-order functions.

  • Question:

Can we implement one concept in terms of the other?

  • Objects in terms of higher-order functions?

  • HOF in terms of objects?

How class are organized


  • All members of package scala

  • All members of package java.lang

  • All members of the singleton object scala.Predef.

Here are the fully qualified names of some types and functions which you have seen so far:

Int 		=> scala.Int
Boolean		=> scala.Boolean
Obejct		=> java.lang.Object
require 	=> scala.predef.require
assert		=> scala.predef.assert


In Java, as well as in Scala, a class can only have one superclass.

But what if a class has several natural supertypes to which it conforms or from which it wants to inherit code?

Here, you could use traits.

A trait is declared like an abstract class, just with trait instead of abstract class.


trait Planar
	def height: Int
	def width : Int
	def surface = height*width


class Square extends Shape with Plannar with Movable...

Traits resemble interfaces in Java, but are more powerful because they can contains fields and concrete methods.

On the other hand, traits cannot have parameters, only classes can


###Top Types


  • Any : the base type of all types, Method: ‘==’, ‘!=’, ‘equals’, ‘hashCode’, ‘toString’

  • AnyRef : The base type of all reference types; Alias of ‘java.lang.Object’

  • AnyVal : The base type of all primitive types.

###The Nothing Type

Nothing is at the bottom of Scala’s type hierarchy. It is a subtype of every other type.

There is no value of type Nothing.

Why is that useful?

  • To signal abnormal termination

  • As an element type of empty collections


Scala’s exception handling is similar to Java’s

The expression:

def error(msg:String) = throw new Error(msg) 

###The Null Type

Every reference class type also has null as a value.

The type of null is Null .

Null is a subtype of every class that inherits from Object; it is incompatible with subtypes of AnyVal

val x = null //x:Null = null

val y:String = null // y:String = null

val z:Int = null //error: type mismatch

if (true) 1 else false                          //> res0: AnyVal = 1



以构建一个Con-Lists为例,Con-List是一个immutable linked list


  • Nil : 构建一个empty列表

  • Cons 一个包含一个element的cell和其余的list部分

Cons-Lists in Scala


trait IntList

class Cons(val head:Int, val tail:IntList) extends IntList


class Nil extends IntList


class Cons(_head:Int, _tail:IntList) extends IntList
  	val heal = _head;
  	val tail = _tail;

Type Parameters


trait List[T]
class Cons[T](val head:T, val tail:List[T]) extends List[T]
class Nil[T] extends List[T] 


trait List[T]
  def isEmpty:Boolean
  def head:T
  def tail:List[T]


class Cons[T](val head:T, val tail:List[T]) extends List[T]
  def isEmpty:Boolean = false


class Nil[T] extends List[T] 
	def isEmpty:Boolean = true
	def head:Nothing = throw new NoSuchElementException("Nil.head")
	def tail:Nothing = throw new NoSuchElementException("Nil.head")

###Generic Functions

和类一样,函数也支持泛型参数[T], 例如下面这个函数创建一个泛型List

def singleton[T](elem:T) = new Cons[T](elem, new Nil[T])


###Type Inference



Types and Evaluation


这一特性叫做:type erasure

使用这一特性的语言有: Java,Scala,Haskell,ML,OCaml.



这次来自希腊,意思是多种形式,In programming, 它表示:

  • 函数的参数可以是多种类型的

  • 某一种类型可以有很多子类型


  • 子类: 可以将一个父类型的指针指向一个子类型

  • 泛型: 函数参数和类的参数可以声明成泛型


已知一个list: List[T],要求返回第n个元素:

def nth[T](n:Int,xs:List[T]):T = 
	if (n==0) xs.head 
	else nth(n-1,xs.tail)

2-11 Functions as Objects


###Functions as Objects


例如A => B这种函数类型其实是scala.Function1[A,B]的缩写,定义为:

package scala

trait Function1[A,B]{

	def apply(x:A):B



Expansion of Function Values


(x:Int) => x*x


	class AnonFun extends Function1[Int,Int]
		def apply(x:Int):Int = x*x
	new AnonFun


new Function1[Int,Int]
	def apply(x:Int) = x*x

Expansion of Function Calls



val f = (x:Int) => x*x



val f = new Function1[Int,Int]{ def apply(x:Int) = x*x }

所以:Functions are just Objects

Functions and Methods


def f(x:Int):Boolean = ...



(x:Int) => f(x)


new Function1[Int,Boolean]
	def apply(x:Int) = f(x)

Objects Everywhere


Scala Doc