How to mix-in a trait to instance?

Viewed 25982

Given a trait MyTrait:

trait MyTrait {
  def doSomething = println("boo")
}

it can be mixed into a class with extends or with:

class MyClass extends MyTrait

It can also be mixed upon instantiating a new instance:

var o = new MyOtherClass with MyTrait
o.doSomething

But...can the trait (or any other if that makes a difference) be added to an existing instance?

I'm loading objects using JPA in Java and I'd like to add some functionality to them using traits. Is it possible at all?

I'd like to be able to mix in a trait as follows:

var o = DBHelper.loadMyEntityFromDB(primaryKey);
o = o with MyTrait //adding trait here, rather than during construction
o.doSomething
5 Answers

Why not use Scala's extend my library pattern?

https://alvinalexander.com/scala/scala-2.10-implicit-class-example

I'm not sure what the return value is of:

var o = DBHelper.loadMyEntityFromDB(primaryKey);

but let us say, it is DBEntity for our example. You can take the class DBEntity and convert it to a class that extends your trait, MyTrait.

Something like:

trait MyTrait {
  def doSomething = {
    println("boo")
  }
}

class MyClass() extends MyTrait

// Have an implicit conversion to MyClass
implicit def dbEntityToMyClass(in: DBEntity): MyClass = 
new MyClass()

I believe you could also simplify this by just using an implicit class.

implicit class ConvertDBEntity(in: DBEntity) extends MyTrait

I particularly dislike the accepted answer here, b/c it overloads the :: operator to mix-in a trait.

In Scala, the :: operator is used for sequences, i.e.:

val x = 1 :: 2 :: 3 :: Nil

Using it as a means of inheritance feels, IMHO, a little awkward.

Related