Skip to content

Instantly share code, notes, and snippets.

// Our generic interface
trait Animal {
def voice: String
}
// Implementation 1
class Dog extends Animal {
override def voice: String = "woof!"
}
// Our generic interface
trait Animal {
def voice: String
}
// Pure definitions
case class Dog()
case class Cat()
// Implementation 1
// Our generic inteface
trait Shape {
def area: Double
}
// Implementation 1
class Circle(radius: Double) extends Shape {
override def area: Double = math.Pi * math.pow(radius, 2)
}
trait Shape {
def area: Double
}
// Shape definition data structures, should be in a diffrent file/namespace
case class Circle(radius: Double)
case class Rectangle(width: Double, length: Double)
// Implementation 1
class CircleShape(radius: Double) extends Shape {
trait Shape {
def area: Double
}
case class Circle(radius: Double)
case class Rectangle(width: Double, length: Double)
// v (no constructor parameters)
class CircleShape extends Shape {
override def area : Double = ??? // radius?
// Won't compile
trait Shape {
// vvv (hmm)
def area(???): Double
}
case class Circle(radius: Double)
case class Rectangle(width: Double, length: Double)
class CircleShape extends Shape {
// Shape is now a parametrized trait
// 'A' is placeholder for `Circle`, `Rectangle` or other shape representation
trait Shape[A] {
def area(a: A): Double
}
case class Circle(radius: Double)
case class Rectangle(width: Double, length: Double)
// We have to extend with Shape[Circle] because we have to pass 'Circle' to `area`
def areaOf[A](shape: A, shapeImpl: Shape[A]): Double = shapeImpl.area(shape)
areaOf(Circle(10), new CircleShape)
// vvvvvvvv
def areaOf[A](shape: A)(implicit shapeImpl: Shape[A]): Double = shapeImpl.area(shape)
// No more implementation objects
areaOf(Circle(10))
implicit val circleShape = new CircleShape
implicit val rectangleShape = new RectangleShape
areaOf(Circle(10))
areaOf(Rectangle(5, 5))