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.