Created
August 15, 2013 21:54
-
-
Save privateblue/6245339 to your computer and use it in GitHub Desktop.
three solutions for the same problem: traits, pattern matching, type class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// our model | |
object model { | |
abstract class X | |
case class A extends X | |
case class B extends X | |
} | |
// some extra behaviour we want to add to our model objects, without polluting them | |
object extra { | |
import model._ | |
trait ExtraBehaviour[T <: X] { | |
def doSomething: String | |
} | |
} | |
// downside of this is that we cannot use the companion object's apply method | |
// to instantiate a model object, as we need to mix in the extra behaviour. and | |
// also the extra behaviour needs to be mixed in for every instance individually. | |
object traits { | |
import model._ | |
import extra._ | |
trait ExtraBehaviourA extends ExtraBehaviour[A] { | |
this: A => | |
def doSomething = "foo" | |
} | |
trait ExtraBehaviourB extends ExtraBehaviour[B] { | |
this: B => | |
def doSomething = "bar" | |
} | |
// usage in client code: | |
(new A with ExtraBehaviourA).doSomething | |
(new B with ExtraBehaviourB).doSomething | |
} | |
// downside of this is that it is less extendible - adding a new implementation is | |
// more complicated. | |
object patternmatching { | |
import model._ | |
import extra._ | |
implicit class Wrapper[T <: X](x: T) extends ExtraBehaviour[T]{ | |
def doSomething = | |
x match { | |
case A() => "foo" | |
case B() => "bar" | |
} | |
} | |
// usage in client code: | |
A().doSomething | |
B().doSomething | |
} | |
object typeclass { | |
import model._ | |
import extra._ | |
implicit class Wrapper[T <: X : ExtraBehaviour](x: T) { | |
def doSomething = implicitly[ExtraBehaviour[T]].doSomething | |
} | |
implicit object ExtraBehaviourA extends ExtraBehaviour[A] { | |
def doSomething = "foo" | |
} | |
implicit object ExtraBehaviourB extends ExtraBehaviour[B] { | |
def doSomething = "bar" | |
} | |
// usage in client code: | |
A().doSomething | |
B().doSomething | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment