1

Say I have a sealed trait Person that requires the definition of a method work :: Unit -> Unit. I then have three case objects Accountant, Doctor, and Lawyer. I can think of two ways to implement this. The first is to override work in the case objects:

sealed trait Person {
  def work(): Unit
}

case object Accountant extends Person {
  override def work(): Unit = println("accountant working")
}
case object Doctor extends Person {
  override def work(): Unit = println("doctor working")
}
case object Lawyer extends Person {
  override def work(): Unit = println("lawyer working")
}

The second is to define work directly in the trait using pattern matching:

sealed trait Person {
  def work(): Unit = this match {
    case Accountant => println("accountant working")
    case Doctor => println("doctor working")
    case Lawyer => println("lawyer working")
  }
}

case object Accountant extends Person
case object Doctor extends Person
case object Lawyer extends Person

The second approach seems much cleaner to me, however it apparently violates the open-closed principle, which states that

software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

For example, if I added a case object Nurse, then in the second implementation, I would have to modify Person; whereas in the first implementation, I would merely have to extend Person.

I was wondering if there is a recommended style or approach in this situation? What could go wrong in the first implementation but not the second?

2

I wouldn't consider this to be a violation of the open-closed principle: because the trait is sealed, the relevant entity isn't just Person, but Person together with its implementations, and isn't open for extension either way!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.