Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mix-in a trait to instance?

Tags:

scala

traits

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 
like image 211
Ant Kutschera Avatar asked Oct 08 '10 18:10

Ant Kutschera


People also ask

Can we create instance of traits?

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.

How do I use traits in Scala?

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.

What is the difference between Scala class and object?

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.

What is a Scala object?

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.


1 Answers

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 
like image 185
Googol Shan Avatar answered Oct 10 '22 02:10

Googol Shan