Home > Software engineering >  Creating a type-sensitive function without changing the parent trait or case classes
Creating a type-sensitive function without changing the parent trait or case classes

Time:10-16

Suppose I have two classes, Person and Business, that are extended by the trait Entity.

trait Entity
case class Person(name: String) extends Entity
case class Business(id: String) extends Entity

Assuming I cannot change Entity, Person and Business (they are in a different file and not to be changed) how can I define a function, say a printEntity, that prints the field name or id, depending on the entity? For example, given instances of Person and Business, how can I do something like this:

object Main extends App {
  val person1: Person = Person("Aaaa Bbbb")
  val business1: Business = Business("0001")
  
  // How can I do something like this?
  person1.printEntity // would call a function that executes println(id)
  business1.printEntity // would call a function that executes println(name)
}

Any ideas are appreciated! Sorry for the lack of context, I am still learning!

CodePudding user response:

This is done via so called "extension methods". In scala 2 this is achieved using implicit wrapper class:

trait Entity
case class Person(name: String) extends Entity
case class Business(id: String) extends Entity

implicit class PersonWrapper(val p: Person) extends AnyVal {
  def printEntity(): Unit = {
    println(p.name)
  }
}

implicit class BusinessWrapper(val b: Business) extends AnyVal {
  def printEntity(): Unit = {
    println(b.id)
  }
}

val person1: Person = Person("Aaaa Bbbb")
val business1: Business = Business("0001")

person1.printEntity()
business1.printEntity()

// prints:
//Aaaa Bbbb
//0001

Note, x.printEntity can be called without parentheses, but, by convention, methods with Unit result type and side effects should be called with explicit empty parentheses.


UPD: As @DmytroMitin pointed out, you should extend implicit wrapper classes from AnyVal. This allows the compiler to avoid actually allocating wrapper class instances at runtime, improving performance.

  • Related