say, I have the following:
trait SomeTrait {
def someMethod: String;
}
object SomeObject extends SomeTrait {
def someMethod = "something";
}
I would like to call "someMethod" using reflection as I have the object name as a String.
Something like:
val objectName = "SomeObject"
val someTrait:SomeTrait = ???.asInstanceOf[SomeTrait]
someTrait.someMethod
or something similar.
Thanks
def companion[T](name : String)(implicit man: Manifest[T]) : T =
Class.forName(name + "$").getField("MODULE$").get(man.erasure).asInstanceOf[T]
val result = companion[SomeTrait]("SomeObject").someMethod
Since scala 2.10, we can use the reflection of Module:
import scala.reflect.runtime.universe
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
val module = runtimeMirror.staticModule("SomeObject")
val obj = runtimeMirror.reflectModule(module)
val someTrait:SomeTrait = obj.instance.asInstanceOf[SomeTrait]
someTrait.someMethod
For classes, this can be done pretty easily using the standard java reflection classOf method. For Scala objects, it is a bit more work, but it still can be done:
trait SomeTrait { def someMethod: String}
object SomeObject extends SomeTrait { def someMethod = "something"}
class SomeClass extends SomeTrait { def someMethod = "something"}
object Main {
def main(args:Array[String]) = {
val someClassTrait:SomeTrait = Class.forName("SomeClass").newInstance().asInstanceOf[SomeTrait]
println("calling someClassTrait: " + someClassTrait.someMethod)
val objectName = "SomeObject$"
val cons = Class.forName(objectName).getDeclaredConstructors();
cons(0).setAccessible(true);
val someObjectTrait:SomeTrait = cons(0).newInstance().asInstanceOf[SomeTrait]
println("calling someObjectTrait: " + someObjectTrait.someMethod)
}
}
//prints:
calling someClassTrait: something
calling someObjectTrait: something
Related
I have a ZIO that looks like this:
ZIO[transactor.Transactor[Task], Serializable, String]
and I need to assert the String, that is in that ZIO with another plain String.
So my question is:
How can I assert the plain String, with the String in the ZIO, or
can I lift the String into that same ZIO, to assert it with this one:
ZIO[transactor.Transactor[Task], Serializable, String]
I´m working with ZIO-Test as my testing framework.
I got this based on the rock the jvm zio course. Important things are highlighted in the comments
package com.w33b
import zio.test._
import zio._
object ZIOAssert extends ZIOSpecDefault {
class ATask
abstract class Transact[ATask] {
def get(): String
def put(ATask: ATask): ATask
}
// This is the mock service that we will use to create a ZLayer
val mockTransact = ZIO.succeed(new Transact[ATask] {
override def get(): String = "hello"
override def put(aTask: ATask): ATask = new ATask
})
// This is the method we are testing and we need a service (Zlayer) associated with it.
// We then use the service to invoke a method to get our return value
def methodUnderTest: ZIO[Transact[ATask], Serializable, String] = {
for {
trans <- ZIO.service[Transact[ATask]]
tVal = trans.get()
} yield tVal
}
def spec = suite("Let's test that ZIO lift")(
test("lets test that lift") {
assertZIO(methodUnderTest)(Assertion.equalTo("hello"))
}
).provide(ZLayer.fromZIO(mockTransact)) // Important to provide the layer or we can't test
}
with ZIO 2.x
val spec = suite("tetst")(
test("whatever"){
val effect: ZIO[transactor.Transactor[Task], Serializable, String] = ???
val expected: String = ???
for {
value <- effect
} yield assertTrue(value == expected)
}
)
In general, you just create here a ZIO with the assertion in the success channel.
I am working with Firebase so I have a lot of return types of type ApiFuture<A>. I'd like to turn them into a Task[A] to work with ZIO effects.
We can create a method to convert all of them using Typeclasses:
trait EffectUtils[F[_]] {
def toEffect[A](a: F[A]): Task[A]
}
object EffectUtils {
implicit val apiFuture: EffectUtils[ApiFuture] = new EffectUtils[ApiFuture] {
override def toEffect[A](a: ApiFuture[A]): Task[A] = Task.effectAsync[A]( cb =>
ApiFutures.addCallback(a, new ApiFutureCallback[A] {
override def onFailure(t: Throwable): Unit = cb(Task.fail(t))
override def onSuccess(result: A): Unit = cb(Task.succeed(result))
})
)
}
implicit class ApiFutureOps[A](f: ApiFuture[A]) {
def toEffect(implicit instance: EffectUtils[ApiFuture]) = instance.toEffect(f)
}
}
Now, when we make an API request and want to convert the result to a ZIO type, it's easy:
import EffectUtils._
object App {
// calling a Firebase function
val record: Task[UserRecord] = firebase.getInstance().auth().getUserByEmailAsync(email).toEffect
If I have a top level object declaration
package com.example
object MyObject {}
how can I convert the string com.example.MyObject into a reference to MyObject?
If you have kotlin-reflect on the classpath then you can use the objectInstance property of KClass
fun main(args: Array<String>) {
val fqn = "com.example.MyObject"
val clz: Class<*> = Class.forName(fqn)
val instance = clz.kotlin.objectInstance
println(instance) // com.example.MyObject#71623278
}
if you don't have kotlin-reflect then you can do it in a plain old java-way
fun main(args: Array<String>) {
val fqn = "com.example.MyObject"
val clz: Class<*> = Class.forName(fqn)
val field: Field = clz.getDeclaredField("INSTANCE")
val instance = field.get(null)
println(instance) // com.example.MyObject#76ed5528
}
you can using kotlin reflection, for example:
val it = Class.forName("com.example.MyObject").kotlin.objectInstance as MyObject;
Same a java code, you need use Class.forName("com.example.MyObject"). Now you have a Java class, but using kotlin extension, it convert to Kotlin class. Class.forName("com.example.MyObject").kotlin
I have the following function to access a property's delegate. It uses Kotlin reflection to get a property's name and Java reflection to get the field.
fun Any.getDelegate<T>(prop: KProperty<T>): Any {
return javaClass.getDeclaredField("${prop.name}\$delegate").let {
it.setAccessible(true)
it.get(this)
}
}
The method is used like this:
val delegate = a.getDelegate(A::b)
However, I would prefer to use it like this:
val delegate = a.b.delegate
The problem with the code above is getting the property name of a.b and getting the instance a from a.b. From what I know about Kotlin, this is probably not possible, however I'd like to see if I can clean up my function at all.
To give a bigger picture of what I'm trying do here's my complete code. I want an observable delegate to which I can add and remove observers using the delegate reference and without creating addition variables.
fun Any.addObservable<T>(prop: KProperty<T>, observer: (T) -> Unit) {
getObservableProperty(prop).observers.add(observer)
}
fun Any.getObservableProperty<T>(prop: KProperty<T>): ObservableProperty<T> {
return getDelegate(prop) as ObservableProperty<T>
}
fun Any.getDelegate<T>(prop: KProperty<T>): Any {
return javaClass.getDeclaredField("${prop.name}\$delegate").let {
it.setAccessible(true)
it.get(this)
}
}
class ObservableProperty<T>(
initialValue: T,
initialObservers: Array<(T) -> Unit> = emptyArray()) : ReadWriteProperty<Any?, T> {
private var value = initialValue
public val observers: MutableSet<(T) -> Unit> = initialObservers.toHashSet()
public override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return value
}
public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) {
this.value = value
observers.forEach { it(value) }
}
}
class A() {
var b by ObservableProperty(0)
}
fun main(args: Array<String>) {
val a = A()
a.addObservable(A::b) {
println("b is now $it")
}
a.b = 1
a.b = 2
a.b = 3
}
Edit:
I just realized that the function also isn't strict because the property delegate field name is referenced by KProperty name, which doesn't require a strong reference to the enclosing class. Here's an example to demonstrate the problem:
class A() {
var foo by ObservableProperty(0)
}
class B() {
var foo by ObservableProperty(0)
}
fun main(args: Array<String>) {
val a = A()
a.addObservable(B::foo) {
println("b is now $it")
}
a.foo = 1
a.foo = 2
a.foo = 3
}
This compiles and runs without error because A::foo and B::foo both result in a field string of "foo$delegate.
Right now reflection is all we can do to get to the delegate object. We are designing a language feature to have direct access to delegate instance, but it's long way to go.
This is how you get the name of a Kotlin Property (although only with an instance of the class). This part will be useful to anyone arriving at this question purely based off its title.
class Stuff(val thing: String)
val stuff = Stuff("cool stuff")
val thingFieldName = "${stuff.thing}\$delegate"
// value of thingFieldName is now "thing"
In terms of getting the delegate itself easier, they say you can now do this:
class Foo {
var bar: String by ReactiveProperty<String>()
}
val foo = Foo()
val bar = foo.bar
val barDelegate = ... // foo.bar$delegate
See ticket.
In Scala, what's the best way to dynamically instantiate an object and invoke a method using reflection?
I would like to do Scala-equivalent of the following Java code:
Class class = Class.forName("Foo");
Object foo = class.newInstance();
Method method = class.getMethod("hello", null);
method.invoke(foo, null);
In the above code, both the class name and the method name are passed in dynamically. The above Java mechanism could probably be used for Foo and hello(), but the Scala types don't match one-to-one with that of Java. For example, a class may be declared implicitly for a singleton object. Also Scala method allows all sorts of symbols to be its name. Both are resolved by name mangling. See Interop Between Java and Scala.
Another issue seems to be the matching of parameters by resolving overloads and autoboxing, described in Reflection from Scala - Heaven and Hell.
There is an easier way to invoke method reflectively without resorting to calling Java reflection methods: use Structural Typing.
Just cast the object reference to a Structural Type which has the necessary method signature then call the method: no reflection necessary (of course, Scala is doing reflection underneath but we don't need to do it).
class Foo {
def hello(name: String): String = "Hello there, %s".format(name)
}
object FooMain {
def main(args: Array[String]) {
val foo = Class.forName("Foo").newInstance.asInstanceOf[{ def hello(name: String): String }]
println(foo.hello("Walter")) // prints "Hello there, Walter"
}
}
The answers by VonC and Walter Chang are quite good, so I'll just complement with one Scala 2.8 Experimental feature. In fact, I won't even bother to dress it up, I'll just copy the scaladoc.
object Invocation
extends AnyRef
A more convenient syntax for reflective
invocation. Example usage:
class Obj { private def foo(x: Int, y: String): Long = x + y.length }
You can call it reflectively one of
two ways:
import scala.reflect.Invocation._
(new Obj) o 'foo(5, "abc") // the 'o' method returns Any
val x: Long = (new Obj) oo 'foo(5, "abc") // the 'oo' method casts to expected type.
If you call the oo
method and do not give the type
inferencer enough help, it will most
likely infer Nothing, which will
result in a ClassCastException.
Author Paul Phillips
The instanciation part could use the Manifest: see this SO answer
experimental feature in Scala called manifests which are a way to get around a Java constraint regarding type erasure
class Test[T](implicit m : Manifest[T]) {
val testVal = m.erasure.newInstance().asInstanceOf[T]
}
With this version you still write
class Foo
val t = new Test[Foo]
However, if there's no no-arg constructor available you get a runtime exception instead of a static type error
scala> new Test[Set[String]]
java.lang.InstantiationException: scala.collection.immutable.Set
at java.lang.Class.newInstance0(Class.java:340)
So the true type safe solution would be using a Factory.
Note: as stated in this thread, Manifest is here to stay, but is for now "only use is to give access to the erasure of the type as a Class instance."
The only thing manifests give you now is the erasure of the static type of a parameter at the call site (contrary to getClass which give you the erasure of the dynamic type).
You can then get a method through reflection:
classOf[ClassName].getMethod("main", classOf[Array[String]])
and invoke it
scala> class A {
| def foo_=(foo: Boolean) = "bar"
| }
defined class A
scala>val a = new A
a: A = A#1f854bd
scala>a.getClass.getMethod(decode("foo_="),
classOf[Boolean]).invoke(a, java.lang.Boolean.TRUE)
res15: java.lang.Object = bar
In case you need to invoke a method of a Scala 2.10 object (not class) and you have the names of the method and object as Strings, you can do it like this:
package com.example.mytest
import scala.reflect.runtime.universe
class MyTest
object MyTest {
def target(i: Int) = println(i)
def invoker(objectName: String, methodName: String, arg: Any) = {
val runtimeMirror = universe.runtimeMirror(getClass.getClassLoader)
val moduleSymbol = runtimeMirror.moduleSymbol(
Class.forName(objectName))
val targetMethod = moduleSymbol.typeSignature
.members
.filter(x => x.isMethod && x.name.toString == methodName)
.head
.asMethod
runtimeMirror.reflect(runtimeMirror.reflectModule(moduleSymbol).instance)
.reflectMethod(targetMethod)(arg)
}
def main(args: Array[String]): Unit = {
invoker("com.example.mytest.MyTest$", "target", 5)
}
}
This prints 5 to standard output.
Further details in Scala Documentation.
Working up from #nedim's answer, here is a basis for a full answer,
main difference being here below we instantiate naive classes. This code does not handle the case of multiple constructors, and is by no means a full answer.
import scala.reflect.runtime.universe
case class Case(foo: Int) {
println("Case Case Instantiated")
}
class Class {
println("Class Instantiated")
}
object Inst {
def apply(className: String, arg: Any) = {
val runtimeMirror: universe.Mirror = universe.runtimeMirror(getClass.getClassLoader)
val classSymbol: universe.ClassSymbol = runtimeMirror.classSymbol(Class.forName(className))
val classMirror: universe.ClassMirror = runtimeMirror.reflectClass(classSymbol)
if (classSymbol.companion.toString() == "<none>") // TODO: use nicer method "hiding" in the api?
{
println(s"Info: $className has no companion object")
val constructors = classSymbol.typeSignature.members.filter(_.isConstructor).toList
if (constructors.length > 1) {
println(s"Info: $className has several constructors")
}
else {
val constructorMirror = classMirror.reflectConstructor(constructors.head.asMethod) // we can reuse it
constructorMirror()
}
}
else
{
val companionSymbol = classSymbol.companion
println(s"Info: $className has companion object $companionSymbol")
// TBD
}
}
}
object app extends App {
val c = Inst("Class", "")
val cc = Inst("Case", "")
}
Here is a build.sbt that would compile it:
lazy val reflection = (project in file("."))
.settings(
scalaVersion := "2.11.7",
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-compiler" % scalaVersion.value % "provided",
"org.scala-lang" % "scala-library" % scalaVersion.value % "provided"
)
)