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
Traits are used to share interfaces and fields between classes. They are similar to Java 8's interfaces. Classes and objects can extend traits, but traits cannot be instantiated and therefore have no parameters.
In scala, trait is a collection of abstract and non-abstract methods. You can create trait that can have all abstract methods or some abstract and some non-abstract methods. A variable that is declared either by using val or var keyword in a trait get internally implemented in the class that implements the trait.
Difference Between Scala Classes and Objects Definition: A class is defined with the class keyword while an object is defined using the object keyword. Also, whereas a class can take parameters, an object can't take any parameter. Instantiation: To instantiate a regular class, we use the new keyword.
In Scala, an object is a named instance with members such as fields and methods. An object and a class that have the same name and which are defined in the same source file are known as companions. Companions has special access control properties, which is covered under Scala/Access modifiers.
I have a idea for this usage:
//if I had a class like this final class Test { def f = println("foo") } trait MyTrait { def doSomething = { println("boo") } } object MyTrait { implicit def innerObj(o:MixTest) = o.obj def ::(o:Test) = new MixTest(o) final class MixTest private[MyTrait](val obj:Test) extends MyTrait }
you can use this trait as below:
import MyTrait._ val a = new Test val b = a :: MyTrait b.doSomething b.f
for your example code:
val o = DBHelper.loadMyEntityFromDB(primaryKey) :: MyTrait o.doSomething
I hope this can help you.
UPDATED
object AnyTrait { implicit def innerObj[T](o: MixTest[T]):T = o.obj def ::[T](o: T) = new MixTest(o) final class MixTest[T] private[AnyTrait](val obj: T) extends MyTrait }
but this pattern has some restrict, you can't use some implicit helper method that defined already.
val a = new Test a.f val b = a :: AnyTrait b.f1 b.f val c = "say hello to %s" :: AnyTrait println(c.intern) // you can invoke String's method println(c.format("MyTrait")) //WRONG. you can't invoke StringLike's method, though there defined a implicit method in Predef can transform String to StringLike, but implicit restrict one level transform, you can't transform MixTest to String then to StringLike. c.f1 val d = 1 :: AnyTrait println(d.toLong) d.toHexString // WRONG, the same as above d.f1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With