Assume you have a couple of classes,
case class Person(name: String, age: Int)
case class Employee(person: Person, salary: Double)
Lets say for some reason,
- You don't want to change this source, but
- You should be able to add features
save(person)
andsave(employee)
, and - You need clearly separate implementations for both the types,
You start by defining a type class,
trait DBObject[T] {
def save(t: T)
}
Then you define an implementation for each of your types as implicit objects,
implicit object PersonDBO extends DBObject[Person] {
def save(p: Person) = //Do whatever you need to do to save p: Person
}
implicit object EmployeeDBO extends DBObject[Employee] {
def save(e: Employee) = //Do whatever you need to do to save e: Employee
}
And then you define your one single generic save method,
def save[T](obj: T)(implicit dbo: DBObject[T]) = dbo.save(obj)
From then onwards you can use save(employee)
to save employees, and save(person)
to save persons.
Also, if you noticed, let's say you want to add a new type Company
. You can give an implicit save
implementation for that one as well in your most recent part of the code, without touching any of the code you have already written!
case class Company(name: String, employees: List[Employee])
implicit object CompanyDBO extends DBObject[Company] {
def save(c: Company) = //Do whatever you need to do to save c: Company
}
Any other goodies you can think about for Type Classes?
Scala 2.10 adds sugar by introducing 'implicit classes' reducing the class and implicit definition in the above comment to,