Traits in Scala UMBC CMSC 331 Basic Properties

Traits in Scala UMBC CMSC 331

Basic Properties 2 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

Simple Example Using Extends 3 trait Similarity { def is. Similar(x: Any): Boolean def is. Not. Similar(x: Any): Boolean = !is. Similar(x) } This trait consists of two methods is. Similar and is. Not. Similar is abstract is. Not. Similar is concrete but written in terms of is. Similar Classes that integrate this trait only have to provide a concrete implementation foris. Similar, is. Not. Similar gets inherited directly from the trait

What’s the output? (Part 1) 4 class Point(xc: Int, yc: Int) extends Similarity { var x: Int = xc var y: Int = yc def is. Similar(obj: Any) = obj. is. Instance. Of[Point] && obj. as. Instance. Of[Point]. x == x }

What’s the output? (Part 2) 5 object Traits. Test extends Application { val p 1 = new Point(2, 3) val p 2 = new Point(2, 4) val p 3 = new Point(3, 3) println(p 1. is. Not. Similar(p 2)) println(p 1. is. Not. Similar(p 3)) println(p 1. is. Not. Similar(2)) }

Mixing in a Trait Using With 6 Consider the running example on pgs 213 -215 of Odersky Since Philosophical and Has. Legs are Traits and Animal is a class we may write: class Frog extends Animal with Philosophical with Has. Legs { override def to. String = “green” override def philosophize =println(“Itain’t easy being “+ to. String +”!”) }

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

Traits with Stackable Modifications 8 Use to stack modifications to a class Consider the Int. Queue class from Odersky (pg 223) abstract class Int. Queue { def get () : Int def put(x : Int) } Now we’ll build a concrete class atop of it

An implementation 9 import scala. collection. mutable. Array. Buffer class Basic. Queue extends Int. Queue{ private val buf = new Array. Buffer[int] def get () : buf. remove(0) def put(x : Int) { buf += x } }

A Trait Useful For the Queue 10 trait Doubling extends Int. Queue { abstract override def put (x : Int) { super. put(2*x) } } Can only be used with Int. Queues This refers to the class that actually uses the trait val queue = new Basic. Int. Queue with Doubling queue. put(10) queue. get()

Two Additional Traits 11 trait Incrementing extends Int. Queue { abstract override def put (x : Int) { super. put(x+1) } } trait Filtering extends Int. Queue { abstract override def put (x : Int) { if (x> = 0) super. put(x) } }

Upper Bounds(1) 12 trait Similar{ def is. Similar(x: Any): Boolean def is. Not. Similar(x: Any): Boolean = !is. Similar(x) } case class My. Int (x : Int) extends Similar { def is. Similar(x : Int) : Boolean = m. is. Instance[My. Int] && m. as. Instance. Of[My. Int]. x = x }

Upper Bounds(2) 13
 trait Observer[T] Involved Example Using Traits 14 case class Change. Event[On. Type](on: On. Type) trait Observer[T]](http://slidetodoc.com/presentation_image_h2/fc2073cfc234e51ed811d4424c022e0d/image-14.jpg)
Involved Example Using Traits 14 case class Change. Event[On. Type](on: On. Type) trait Observer[T] { this: T with Observer[T] => The param is the type of thing that changed 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 type Change. Handler = { def changed(c: Change. Event[T with Observer[T]]): Unit } A type that matched anything with that method and signature private var observers: List[Change. Handler] = Nil def add. Observer(c: Change. Handler) = synchronized { observers = c : : observers } … } }
![Rest of Trait Definition 15 trait Observer[T] { … def remove. Observer(c: Change. Handler)= Rest of Trait Definition 15 trait Observer[T] { … def remove. Observer(c: Change. Handler)=](http://slidetodoc.com/presentation_image_h2/fc2073cfc234e51ed811d4424c022e0d/image-15.jpg)
Rest of Trait Definition 15 trait Observer[T] { … def remove. Observer(c: Change. Handler)= synchronized { observers -= c } protected def update. Observers() = synchronized { val ch = Change. Event(this) Observers. foreach(i =>i. changed(ch)) } } A Change. Event has been made ( a case class) , tell each observer about the change.
![Testing 16 class Shibby extends Observer[Shibby] { private var _count = 0 def count Testing 16 class Shibby extends Observer[Shibby] { private var _count = 0 def count](http://slidetodoc.com/presentation_image_h2/fc2073cfc234e51ed811d4424c022e0d/image-16.jpg)
Testing 16 class Shibby extends Observer[Shibby] { private var _count = 0 def count = synchronized{_count} def inc = synchronized { _count += 1 This class generates the update. Observers() events and then tells the } Observers about it } val s = new Shibby
![Testing 17 object Dibby { def changed(c: Change. Event[Shibby]) { println(“Dibby changed: + c. Testing 17 object Dibby { def changed(c: Change. Event[Shibby]) { println(“Dibby changed: + c.](http://slidetodoc.com/presentation_image_h2/fc2073cfc234e51ed811d4424c022e0d/image-17.jpg)
Testing 17 object Dibby { def changed(c: Change. Event[Shibby]) { println(“Dibby changed: + c. on. count)} } These classes respond to the changes object Doo{ def changed(c: Change. Event[Shibby]) { println(“Doo changed: + c. on. count)} }

Observer Get Events 18 s. add. Observer(Dibby) s. add. Observer(Doo) s. inc Dibby changed 1 Doo changed 1 s. remove. Observer(Dibby) s. inc Doo changed 2

References 19 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
- Slides: 19