I have a trait and an object inherited from this trait:
trait MyTrait {
def method1(a: Int)
}
object MyObject extends MyTrait {
def method1(a: Int) = //....
}
Assuming I have only the full name of an object as a string (namespace + its name) and knowing it's inherited from MyTrait, how do I
create it at runtime
call its method method1
return it to a calling code so that other clients can use it?
I read about reflection in Scala, but, oddly enough, almost all I found was about creating a class at runtime.
UPDATE:
I wonder, why doesn't this work:
scala> object MyObject { def method1(a: Int) = 123456 }
defined module MyObject
scala> val cs = Class.forName("MyObject")
java.lang.ClassNotFoundException: MyObject
due to the error java.lang.ClassNotFoundException: MyObject
If you want to get an instance of a singleton scala object via reflection, you can try this:
package code
object ReflectTest extends App{
val clazz = Class.forName("code.MyObject$")
val myObj = clazz.getField("MODULE$").get(classOf[MyTrait]).asInstanceOf[MyTrait]
println(myObj.method1(2))
}
trait MyTrait {
def method1(a: Int):Int
}
object MyObject extends MyTrait {
def method1(a: Int) = a + 1
}
Now I'm not a big fan of obtaining instances of scala objects via reflection (seems kinds silly given that it's a singleton) but maybe you have a valid use case for this.
Related
I have a simple trait
trait SomeTrait {
val sourceData: SourceData
}
SourceData class has constructor parameter p: Array[String].
Now, when I extend this trait in Object, we must provide implementation for sourceData.
object SomeObject extends SomeTrait {
override val sourceData: SourceData = ???
def main(sysArgs: Array[String]){...}
}
But what if class SourceData needs sysArgs from main method, how can I override sourceData in main method, not in body of SomeObject. Something like this:
object SomeObject extends SomeTrait {
def main(sysArgs: Array[String]){
override val sourceData: SourceData = new SourceData(sysArgs)
}
}
I do not want to use var, as val immutability is preferred. And also I want to have trait with no implementation in order to force all sub classes to implement sourceData. What other solution I have for this?
You can't avoid mutability in this situation. sourceData must have a value before main is called, and main must be able to change that value, so the value must be mutable.
One option is to make sourceData a def (which is a good idea anyway) and have it access a private var in SomeObject:
trait SomeTrait {
def sourceData: SourceData
}
object SomeObject extends SomeTrait {
private var mySource: SourceData = ???
def sourceData = mySource
def main(sysArgs: Array[String]) = {
mySource = new SourceData(sysArgs)
}
}
The root problem here is having a top-level object that needs run-time initialisation. This is required because SomeObject is a top-level object that is accessed directly from other parts of the code.
The solution to this is dependency injection rather than a global object.
trait SomeTrait {
def sourceData: SourceData
}
object SomeObject {
case class SomeData(sourceData: SourceData) extends SomeTrait
def main(sysArgs: Array[String]) = {
val theSource = SomeData(SourceData(sysArgs))
// Pass this instance to the rest of the code that needs it
restOfTheProgram(theSource)
}
}
The rest of the code uses the instance of SomeTrait that is passed to it rather than using SomeObject directly.
There is no way to do that in Scala. You need to have a class inherit SomeTrait and instantiate it from the main method.
Given a case class and companion object like below:
case class Example(a: String)
object Example {
implicit def concat(b: String): Example =
Example(this.a + b)
}
How to make the implicit method compile? In other words, is it possible to refer to the current instance that the implicit method has been called upon?
I think what you want is the following:
object Foo {
implicit class RichExample(val e: Example) {
def concat(b: String): Example = Example(e.a + b)
}
}
or using an anonymous implicit class
object Foo {
implicit def richExample(e: Example) = new {
def concat(b: String): Example = Example(e.a + b)
}
}
Usage
You can then use it like this
import Foo._
Example("foo").concat("bar")
Import and companion object
If the object is called Example, then it becomes the companion object for class Example, and you do not have to import Foo._ to use the extension method.
I am currently struggling with spray-json writing a protocol for my data model. For deserialization of JSON data to my data transfer objects, a DAO has to be contacted to check if an appropriate object exists, otherwise a DeserializationException should be thrown.
So far, I have the following:
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object MyDtoJsonFormat extends RootJsonFormat[MyDto] {
override def write(obj: MyDto): JsValue = // Serialization implementation
override def read(json: JsValue): MyDto = {
// parse the JSON, get some parameters, let them be a, b, c
dtoLookup(a, b, c) match {
case Some(dto: MyDto) => dto
case None => throw new DeserializationException("Cannot retrieve object from DAO")
}
}
}
def dtoLookup(a: SomeType, b: SomeOtherType, c: YetAnotherType)(implicit dao: MyDAO): Option[MyDto] = {
// lookup the MyDTO with the dao instance
}
}
My test looks like the following:
class MyJsonProtocolTest extends FlatSpec with Matchers {
implicit val MyDAO = // some test instance, can be a mock object
"The protocol" should "serialize a DTO" in {
val dto: MyDTO = ...
dto.toJson.compactPrint should be("{...}")
}
}
However, the compiler complains that it cannot find the implicit MyDAO when trying to compile the MyJSONProtocol. In When testing Spray services with Scalatest, how to introduce implicit values? I asked yesterday, I was suggested to pass in the implicit parameter directly into the method, but I cannot do this here because the read method is defined in the RootJsonFormat.
When I call the dtoLookup method directly from my test code, it succeeds.
So, how do I get the MyDAO instance into my special JSON format?
One option is to make the implicit parameter a constructor parameter to one of the classes being used. This might require that you turn one of your objects into a class. Then you can make an get method on the companion object of that class that uses an implicit in scope to construct the class with the desired argument.
This doesn't really have to do with spray or scalatest, rather it's just an issue with implicits and implicit scope. Here's a simplified version:
object MyJsonProtocol {
implicit object MyDtoJsonFormat {
def read(x: Int) = dtoLookup
}
def dtoLookup(implicit x: Int) = x + 1
}
And you might consider changing that to:
class MyJsonProtocol(implicit x: Int) {
implicit object MyDtoJsonFormat {
def read(x: Int) = dtoLookup
}
def dtoLookup = x + 1
}
object MyJsonProtol {
def get(implicit x: Int) = new MyJsonProtocol
}
And then you can use this with an implicit in scope:
class MyJsonProtocolTest {
implicit val x = 5
val proto = MyJsonProtol.get
val myReadValue = proto.MyDtoJsonFormat.read //6
}
You can read about the rules for implicit scopes here, especially relevant might be the "Where do Implicits Come From" section.
I have some problem calling my Scala code from Java.
Here is my Scala Class:
case class Foobar(foo: String) extends FoobarParent
object Foobar {
implicit object Format extends Format[Foobar] {
def writes(Foobar: foobar): JsValue = {
....
}
implicit def reads(json: JsValue): JsResult[Foobar] = {
...
}
}
}
Now when I have a method with the following signature:
def publish[T <: FoobarParent](foobarParent: T)(implicit writes: Writes[T]): Unit = {...}
This works fine when calling from Scala code, I simply just do publish[Foobar] (Foobar(...))
However in Java, the signature looks likes this in my IDE:
publish (T FoobarParent, Writes<T> writes)
Now my question is what/how do I fulfil those two parameters in Java?
You usually can get an object's instance like this: Foobar$.MODULE$
and the nested one like this: Foobar.Format$.MODULE$
There's a problem with the companion object here though, because it gets compiled as a different class. It will create a class named Foobar$ which is not of the type Foobar nor does it extends FoobarParent. So you can't just call publish(Foobar$.MODULE$, Foobar.Format$.MODULE$);. I think you'll just have to create a new instance:
publish(new Foobar("..."), Foobar.Format$.MODULE$);
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
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
An existing runtime object in the JVM has a certain size on the heap. Adding a trait to it would mean altering its size on the heap, and changing its signature.
So the only way to go would be to do some kind of transformation at compile time.
Mixin composition in Scala occurs at compile time. What compiler could potentially do is create a wrapper B around an existing object A with the same type that simply forwards all calls to the existing object A, and then mix in a trait T to B. This, however, is not implemented. It is questionable when this would be possible, since the object A could be an instance of a final class, which cannot be extended.
In summary, mixin composition is not possible on existing object instances.
UPDATED:
Related to the smart solution proposed by Googol Shan, and generalizing it to work with any trait, this is as far as I got. The idea is to extract the common mixin functionality in the DynamicMixinCompanion trait. The client should then create a companion object extending DynamicMixinCompanion for each trait he wants to have the dynamic mixin functionality for. This companion object requires defining the anonymous trait object gets created (::).
trait DynamicMixinCompanion[TT] {
implicit def baseObject[OT](o: Mixin[OT]): OT = o.obj
def ::[OT](o: OT): Mixin[OT] with TT
class Mixin[OT] protected[DynamicMixinCompanion](val obj: OT)
}
trait OtherTrait {
def traitOperation = println("any trait")
}
object OtherTrait extends DynamicMixinCompanion[OtherTrait] {
def ::[T](o: T) = new Mixin(o) with OtherTrait
}
object Main {
def main(args: Array[String]) {
val a = "some string"
val m = a :: OtherTrait
m.traitOperation
println(m.length)
}
}
I usually used a implicit to mix in a new method to an existing object.
See, if I have some code as below:
final class Test {
def f = "Just a Test"
...some other method
}
trait MyTrait {
def doSomething = {
println("boo")
}
}
object HelperObject {
implicit def innerObj(o:MixTest) = o.obj
def mixWith(o:Test) = new MixTest(o)
final class MixTest private[HelperObject](obj:Test) extends MyTrait
}
and then you can use MyTrait method with an already existing object Test.
val a = new Test
import HelperObject._
val b = HelperObject.mixWith(a)
println(b.f)
b.doSomething
in your example, you can use like this:
import HelperObject._
val o = mixWith(DBHelper.loadMyEntityFromDB(primaryKey));
o.doSomething
I am thinking out a prefect syntax to define this HelperObject:
trait MyTrait {
..some method
}
object MyTrait {
implicit def innerObj(o:MixTest) = o.obj
def ::(o:Test) = new MixTest(o)
final class MixTest private[MyTrait](obj:Test) extends MyTrait
}
//then you can use it
val a = new Test
val b = a :: MyTrait
b.doSomething
b.f
// for your example
val o = DBHelper.loadMyEntityFromDB(primaryKey) :: MyTrait
o.doSomething
What about an implicit class? It seems easier to me compared to the way in the other answers with a final inner class and a "mixin"-function.
trait MyTrait {
def traitFunction = println("trait function executed")
}
class MyClass {
/**
* This inner class must be in scope wherever an instance of MyClass
* should be used as an instance of MyTrait. Depending on where you place
* and use the implicit class you must import it into scope with
* "import mypackacke.MyImplictClassLocation" or
* "import mypackage.MyImplicitClassLocation._" or no import at all if
* the implicit class is already in scope.
*
* Depending on the visibility and location of use this implicit class an
* be placed inside the trait to mixin, inside the instances class,
* inside the instances class' companion object or somewhere where you
* use or call the class' instance with as the trait. Probably the
* implicit class can even reside inside a package object. It also can be
* declared private to reduce visibility. It all depends on the structure
* of your API.
*/
implicit class MyImplicitClass(instance: MyClass) extends MyTrait
/**
* Usage
*/
new MyClass().traitFunction
}
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.