sealed abstract class Employee(val name: String, years: Int, baseSalary: BigDecimal) { //abstract method def yearsContribution(): BigDecimal //do the same logic with different data and sub-logic in each subclass def salary(): BigDecimal = baseSalary + yearsContribution() override def toString: String = s"My name is $name and I've been working here for $years years." } class OfficeWorker(name: String, years: Int) extends Employee(name, years, baseSalary = BigDecimal(1000)) { override def yearsContribution(): BigDecimal = years * 30 } //extra fields class FieldWorker(name: String, years: Int, physicalWork: Boolean) extends Employee(name, years, baseSalary = BigDecimal(800)) { override def yearsContribution(): BigDecimal = years * (if (physicalWork) 40 else 30) } object EmloyeeTestRunner extends App { val o = new OfficeWorker("joe", 12) val f = new FieldWorker("jack", 8, true) Seq[Employee](o, f).foreach { e ⇒ println(s"$e. I earn ${e.salary()}") } }