Presentation is loading. Please wait.

Presentation is loading. Please wait.

UMBC CMSC 331 Traits in Scala. 2 Basic Properties Traits are used to define object types by specifying the signature of the supported methods. Unlike.

Similar presentations


Presentation on theme: "UMBC CMSC 331 Traits in Scala. 2 Basic Properties Traits are used to define object types by specifying the signature of the supported methods. Unlike."— Presentation transcript:

1 UMBC CMSC 331 Traits in Scala

2 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 3 Simple Example Using Extends 3 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 4 What’s the output? (Part 1) 4 class Point(xc: Int, yc: Int) extends Similarity { var x: Int = xc var y: Int = yc def isSimilar(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == x }

5 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 6 Mixing in a Trait Using With 6 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 7 The Ordered Trait 7 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 8 Traits with Stackable Modifications 8 Use to stack modifications to a class Consider the IntQueue class from Odersky (pg 223) abstract class IntQueue { def get () : Int def put(x : Int) } Now we’ll build a concrete class atop of it

9 9 An implementation 9 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 10 A Trait Useful For the Queue 10 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 Doubling queue.put(10) queue.get()

11 11 Two Additional Traits 11 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 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 13 Upper Bounds(2) 13

14 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 Traits 14 The param is the type of thing that changed this this The type of thing for this in the trait is just the type of the thing we’ve mixed Observer into. We don’t know T till runtime. Using this as shown is called a self type – see Odersky pg 537 A type that matched anything with that method and signature

15 15 Rest of Trait Definition 15 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 16 class Shibby extends Observer[Shibby] { private var _count = 0 def count = synchronized{_count} def inc = synchronized { _count += 1 updateObservers() } val s = new Shibby Testing 16 This class generates the events and then tells the Observers about it

17 17 Testing 17 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 18 Observer Get Events 18 s.addObserver(Dibby) s.addObserver(Doo) s.inc Dibby changed 1 Doo changed 1 s.removeObserver(Dibby) s.inc Doo changed 2

19 19 References 19 A tour of Scala : Traits (see http://www.scala- lang.org/node/126)http://www.scala- lang.org/node/126 Programming in Scala, Martin Odersky et al, Artima press 2009 Beginning Scala, David Pollak, Apress, 2009


Download ppt "UMBC CMSC 331 Traits in Scala. 2 Basic Properties Traits are used to define object types by specifying the signature of the supported methods. Unlike."

Similar presentations


Ads by Google