umbc cmsc 331 traits in scala. 2 basic properties traits are used to define object types by...

19
1 UMBC CMSC 331 Traits in Scala Traits in Scala

Upload: ruby-jones

Post on 30-Dec-2015

220 views

Category:

Documents


3 download

TRANSCRIPT

1

UMBCCMSC 331

Traits in ScalaTraits in Scala

2

Basic Properties

Traits are used to define object types by specifying the signature of the supported methods.

Unlike Java, Scala allows traits to be partially implemented; i.e. it is possible to define default implementations for some methods.

Traits may not have constructors

2

3

Simple Example Using Extends3

trait Similarity { def isSimilar(x: Any): Boolean def isNotSimilar(x: Any): Boolean = !isSimilar(x)}

This trait consists of two methods isSimilar and isNotSimilar isSimilar is abstract isNotSimilar is concrete but written in terms of isSimilar

Classes that integrate this trait only have to provide a concrete implementation forisSimilar, isNotSimilar gets inherited directly from the trait

4

What’s the output? (Part 1)4

class Point(xc: Int, yc: Int) extends Similarity {var x: Int = xcvar y: Int = yc def isSimilar(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == x}

5

What’s the output? (Part 2)5

object TraitsTest extends Application {val p1 = new Point(2, 3)val p2 = new Point(2, 4)val p3 = new Point(3, 3) println(p1.isNotSimilar(p2)) println(p1.isNotSimilar(p3)) println(p1.isNotSimilar(2))}

6

Mixing in a Trait Using With6

Consider the running example on pgs 213-215 of Odersky

Since Philosophical and HasLegs are Traits and Animal is a class we may write:

class Frog extends Animal with Philosophical with HasLegs {override def toString = “green”override def philosophize =println(“Itain’t easy being “+ toString +”!”)

}

7

The Ordered Trait7

Thin vs. Rich Interfaces Rich has many methods (easier in theory for client) Thin has fewer – easier for implementer (see Odersky)

The Ordered Trait If Interface is rich then must supply <, > , <=, >= instead

want a trait with a single method (here is an example)

class Rational (n : Int, d : Int) extends Ordered[Rational]

{ def compare (that: Ratioonal) = (this.numer * that.denom)– (that.numer * this.denom)

}

8

Traits with Stackable Modifications8

Use to stack modifications to a classConsider the IntQueue class from Odersky

(pg 223)

abstract class IntQueue {def get () : Intdef put(x : Int)

}

Now we’ll build a concrete class atop of it

9

An implementation9

import scala.collection.mutable.ArrayBuffer

class BasicQueue extends IntQueue{private val buf = new ArrayBuffer[int]

def get () : buf.remove(0) def put(x : Int) { buf += x }

}

10

A Trait Useful For the Queue10

trait Doubling extends IntQueue {abstract override def put (x : Int) { super.put(2*x) }

}

Can only be used with IntQueues

This refers to the class that actually

uses the trait

val queue = new BasicIntQueue with Doublingqueue.put(10)queue.get()

11

Two Additional Traits11

trait Incrementing extends IntQueue {abstract override def put (x : Int) { super.put(x+1) }

}

trait Filtering extends IntQueue {abstract override def put (x : Int) { if (x> = 0) super.put(x)}

}

12

trait Similar{ def isSimilar(x: Any): Boolean def isNotSimilar(x: Any): Boolean = !isSimilar(x)}

case class MyInt (x :Int) extends Similar { def isSimilar(x :Int) : Boolean = m.isInstance[MyInt] && m.asInstanceOf[MyInt].x = x}

trait Similar{ def isSimilar(x: Any): Boolean def isNotSimilar(x: Any): Boolean = !isSimilar(x)}

case class MyInt (x :Int) extends Similar { def isSimilar(x :Int) : Boolean = m.isInstance[MyInt] && m.asInstanceOf[MyInt].x = x}

Upper Bounds(1)12

13

Upper Bounds(2)13

14

case class ChangeEvent[OnType](on: OnType)

trait Observer[T] { this: T with Observer[T] =>

type ChangeHandler = { def changed(c: ChangeEvent[T with Observer[T]]): Unit }

private var observers: List[ChangeHandler] = Nil def addObserver(c: ChangeHandler) = synchronized { observers = c :: observers } … }}

Involved Example Using Traits14

The param is the type of thing that changed

The type of thing for this this in the trait is just the type of the thing we’ve mixed Observer into. We don’t know T till runtime. Using thisthis as shown is called a self type – see Odersky pg 537

A type that matched anything with that method and signature

15

Rest of Trait Definition15

trait Observer[T] { … def removeObserver(c: ChangeHandler)= synchronized { observers -= c }

protected def updateObservers() = synchronized { val ch = ChangeEvent(this) Observers.foreach(i =>i.changed(ch)) }}

A ChangeEvent has been made ( a case class) , tell each observer about the change.

16

class Shibby extends Observer[Shibby] { private var _count = 0 def count = synchronized{_count} def inc = synchronized { _count += 1 updateObservers() }}

val s = new Shibby

Testing16

This class generates the events and then tells the Observers about it

17

Testing17

object Dibby { def changed(c: ChangeEvent[Shibby]) { println(“Dibby changed: + c.on.count)}}

object Doo{ def changed(c: ChangeEvent[Shibby]) { println(“Doo changed: + c.on.count)}}

These classes respond to the changes

18

Observer Get Events18

s.addObserver(Dibby)s.addObserver(Doo)

s.incDibby changed 1Doo changed 1

s.removeObserver(Dibby)s.incDoo changed 2

19

References19

A tour of Scala : Traits (see http://www.scala-lang.org/node/126)

Programming in Scala, Martin Odersky et al, Artima press 2009

Beginning Scala, David Pollak, Apress, 2009