I'ld like to wrap all methods of a class a generic way. So I assume I don't know the methods the class is implementing and AOP is not an alternative.
Groovy metaprogramming allows to redefine methods even with parameters but how to do that when you get a list of parameters from reflection.
someClass.metaClass.methods.each { method ->
someClass.metaClass.'${method.name}' = { /* how to define parameters knowing I get them from method.parameterTypes */
}
}
Thanks in advance for the help.
What about invokeMethod ?
Update: As #Tim commented, you can use getMetaMethod to execute the old method:
class A {
def methodA(String a) { "executing methodA..." }
def methodB(String b, Float c) {}
def methodC() {}
}
A.metaClass.invokeMethod = { String method, args ->
def ret = delegate.class.metaClass.getMetaMethod(method, args)?.invoke( delegate, args )
"[intercepted $method] $ret"
}
def a = new A()
assert a.methodA("a") == "[intercepted methodA] executing methodA..."
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.
Let's say I have the following Java class:
public class A {
public Result method1(Object o) {...}
public Result method2(Object o) {...}
...
public Result methodN(Object o) {...}
}
Then, in my Kotlin code:
fun myFunction(...) {
val a: A = ...
val parameter = ...
val result = a.method1(parameter) // what if i want methodX?
do more things with result
}
and I want to be able to choose which methodX will be called inside myFunction. in Java, I would pass A::method7 as an argument and call it. in Kotlin it doesn't compile. How should I solve it in Kotlin?
You can also pass the method reference in Kotlin (without needing the heavy hammer that is reflection):
fun myFunction(method: A.(Any) -> Result) {
val a: A = ...
val parameter = ...
val result = a.method(parameter)
do more things with result
}
myFunction(A::method1)
myFunction {/* do something in the context of A */}
This declares method as part of A, meaning you can call it with normal object.method() notation. It Just Works™ with the method reference syntax.
There's also another form that works with the same call syntax, but makes A more explicit:
fun myFunction(method: (A, Any) -> Result) { ... }
myFunction(A::method1)
myFunction {a, param -> /* do something with the object and parameter */}
You can actually do this exactly like you wanted to:
fun myFunction(kFunction: KFunction2<A, #ParameterName(name = "any") Any, Result>) {
val parameter = "string"
val result: Result = kFunction(A(), parameter)
//...
}
myFunction(A::method1)
myFunction(A::method2)
I want to use the values of all properties that have some annotation. For the most part my code works, I get all the properties and only take those that have that annotation.
private inline fun <reified A : Annotation> (target: Any) {
target::class.memberProperties
.filter { it.annotations.any { annotation -> annotation is A } }
.forEach {
// How do I get the value here?
}
}
I wanted to use it.get(...) but get expects a Nothing as parameter. Same goes for getter. Calling it.call(target) does work but it looks wrong since there is an actuall get which I don't know how to invoke.
So what is the correct way of getting the properties value?
The problem boils down to the fact that T::class gives you a KClass<T>, whereas t::class gives you a KClass<out T>. Consider the following:
class Foo {
val foo = 2
val bar = 3
}
fun f() {
val any: Any = Foo()
any::class.memberProperties.forEach {
println(it.get(2)) // Oops
}
}
This would essentially attempt to access 2.foo and 2.bar, but it's not allowed because get errs on the side of caution instead of allowing a parameter of type Any. It appears doing t.javaClass.kotlin will produce a KClass<T>, however. Misusing it as above causes an IllegalArgumentException.
You can give the compiler some more help by providing a compile-time guarantee that the KClass will be for the type and nothing else:
private inline fun <reified A : Annotation, reified T : Any> foo(target: T) {
T::class.memberProperties
.filter { it.annotations.any { annotation -> annotation is A } }
.forEach {
println(it.get(target))
}
}
Unfortunately, I don't know if it's possible to specify A while deducing T from target. I haven't found a way past calling it like foo<Attr, Bar>(bar).
Alternatively, you can go through javaClass, though I'd wager it's less portable:
private inline fun <reified A : Annotation> foo(target: Any) {
target.javaClass.kotlin.memberProperties
.filter { it.annotations.any { annotation -> annotation is A } }
.forEach {
println(it.get(target))
}
}
We know this won't run into the above problem because we pass the same object in both cases. This also looks nicer on the caller's side, which might be worth the portability hit, assuming there is one.
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"
)
)
To make debug-time introspection into classes easy, I'd like to make a generic toString method in the base class for the objects in question. As it's not performance critical code, I'd like to use Reflection to print out field name/value pairs ("x=1, y=2" etc).
Is there an easy way to do this? I tried several potential solutions, and ran up against security access issues, etc.
To be clear, the toString() method in the base class should reflectively iterate over public vals in any classes that inherit from it, as well as any traits that are mixed in.
Example:
override def toString() = {
getClass().getDeclaredFields().map { field:Field =>
field.setAccessible(true)
field.getName() + ": " + field.getType() + " = " + field.get(this).toString()
}.deepMkString("\n")
}
Uses Java Reflection API, so don't forget to import java.lang.reflect._
Also, you may need to catch IllegalAccessException on the field.get(this) calls in some scenarios, but this is just meant as a starting point.
Are you aware the Scala case classes get these compiler-generated methods:
toString(): String
equals(other: Any): Boolean
hashCode: Int
They also get companion objects for "new-less" constructors and pattern matching.
The generated toString() is pretty much like the one you describe.
import util._ // For Scala 2.8.x NameTransformer
import scala.tools.nsc.util._ // For Scala 2.7.x NameTransformer
/**
* Repeatedly run `f` until it returns None, and assemble results in a Stream.
*/
def unfold[A](a: A, f: A => Option[A]): Stream[A] = {
Stream.cons(a, f(a).map(unfold(_, f)).getOrElse(Stream.empty))
}
def get[T](f: java.lang.reflect.Field, a: AnyRef): T = {
f.setAccessible(true)
f.get(a).asInstanceOf[T]
}
/**
* #return None if t is null, Some(t) otherwise.
*/
def optNull[T <: AnyRef](t: T): Option[T] = if (t eq null) None else Some(t)
/**
* #return a Stream starting with the class c and continuing with its superclasses.
*/
def classAndSuperClasses(c: Class[_]): Stream[Class[_]] = unfold[Class[_]](c, (c) => optNull(c.getSuperclass))
def showReflect(a: AnyRef): String = {
val fields = classAndSuperClasses(a.getClass).flatMap(_.getDeclaredFields).filter(!_.isSynthetic)
fields.map((f) => NameTransformer.decode(f.getName) + "=" + get(f, a)).mkString(",")
}
// TEST
trait T {
val t1 = "t1"
}
class Base(val foo: String, val ?? : Int) {
}
class Derived(val d: Int) extends Base("foo", 1) with T
assert(showReflect(new Derived(1)) == "t1=t1,d=1,??=1,foo=foo")
Scala doesn't generate any public fields. They're all going to be private. The accessor methods are what will be public, reflect upon those. Given a class like:
class A {
var x = 5
}
The generated bytecode looks like:
private int x;
public void x_$eq(int);
public int x();