I'm trying to invoke the newInstance method of a constructor of a Scala class (case class or usual class, both are affected).
However, I'm running into a IllegalArgumentException with the hint wrong number of arguments.
Consider the following:
case class Vec2(x: Float, y: Float)
object TestApp {
def main(args: Array[String]) {
//after some research I found the last constructor always to be the default
val ctor = classOf[Vec2].getConstructors.last
println("ctor = " + ctor)
println("takes parameters: " + ctor.getParameterTypes.length)
val params = new Array[Float](2)
params.update(0, 1.0f)
params.update(1, -1.0f)
println("num parameters: " + params.length)
println("trying to create new instance...")
try {
val x = ctor.newInstance(params)
println("new instance: " + x)
}
catch {
case ex => ex.printStackTrace
}
}
The output is as follows:
ctor = public pd.test.Vec2(float,float)
takes parameters: 2
num parameters: 2
trying to create new instance...
java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at pd.test.TestApp$.main(TestApp.scala:60)
at pd.test.TestApp.main(TestApp.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
I have experienced something like this in Java once. In that case the class I was trying to instantiate was an inner class of another class, so Java expected an implicit additional parameter, which was either the Class object of the enclosing class (if the class was declared as static), or an instance of the enclosing class.
However, in this case there is no enclosing class of Vec2, unless Scala adds one internally (though, java.lang.Class.getEnclosingClass() returns null for me).
So my question is how to instantiate Scala classes using reflection? Are there any additional parameters Scala constructors expect implicitly?
The newInstance method takes a varargs parameter. In Scala (unlike Java), you can't just pass an array and have it automatically treated as all the arguments. If that's what you want you need to do it explicitly like this:
ctor.newInstance(params:_*)
What you're doing at the moment is passing an array with 2 elements as the first argument to the constructor.
Related
Let records be stream/collection and extract function which transforms data form an element of such collection.
Is there a way in Kotlin to write
records.map {extract(it)}
without explicitely applying(it) ?
E.g. records.map(extract) or records.map {extract}
If extract is a value (local variable, property, parameter) of a functional type (T) -> R or T.() -> R for some T and R, then you can pass it directly to map:
records.map(extract)
Example:
val upperCaseReverse: (String) -> String = { it.toUpperCase().reversed() }
listOf("abc", "xyz").map(upperCaseReverse) // [CBA, ZYX]
If extract is a top-level single argument function or a local single argument function, you can make a function reference as ::extract and pass it to map:
records.map(::extract)
Example:
fun rotate(s: String) = s.drop(1) + s.first()
listOf("abc", "xyz").map(::rotate) // [bca, yzx]
If it is a member or an extension function of a class SomeClass accepting no arguments or a property of SomeClass, you can use it as SomeClass::extract. In this case, records should contain items of SomeType, which will be used as a receiver for extract.
records.map(SomeClass::extract)
Example:
fun Int.rem2() = this % 2
listOf("abc", "defg").map(String::length).map(Int::rem2) // [1, 0]
Since Kotlin 1.1, if extract is a member or an extension function of a class SomeClass accepting one argument, you can make a bound callable reference with some receiver foo:
records.map(foo::extract)
records.map(this::extract) // to call on `this` receiver
Example:
listOf("abc", "xyz").map("prefix"::plus) // [prefixabc, prefixxyz]
(runnable demo with all the code samples above)
you could use method reference (similar to Java).
records.map {::extract}
take a look at the function references examples on kotlin docs
https://kotlinlang.org/docs/reference/reflection.html#function-references
I have a php script which was written on php 5.6.19, works on 5.3 version to, with some installed addons.
I decide to try execute it on php7.
The special of the script that I am initializing a class with parameter by reference via creating a new instance with Reflection::class. And there warning then waited variable by reference but value received.
Definition of the class' constructor method tried to create an instance from:
public function __construct($user, IDatabase &$repository, $errors = null);
Sample of code where this constructor is used:
// define manager type to create (all managers has the same constructor)
$manager = $managersNamespace . ucfirst($this->_manager) . "Manager";
// trying to create the manager
// !!!And here a Warning occurs
$reflect = new \ReflectionClass($manager);
$manager = $reflect->newInstance($user, $database, $errors);
After these I am invoking a method I need, and here the fatal error with stopped the script:
$method = "show" . ucfirst($this->_page) . "Page";
$reflect->getMethod($method)->invoke($manager);
I didn't see any changes in documentation. Anyone had the same issue?
First and foremost, why are you passing an object by reference !?
Objects have pass-by-reference semantics, forcibly trying to pass objects by reference has not made good sense since PHP 4.
Just remove the & ...
Let's ignore that, and pretend there is still a problem, so that you can try to understand what is going on.
To break down the problem, first you need to understand the distinction between a variable and an expression:
mine(1 + 2);
The argument to mine has no name, it's represented by a temporary variable in the engine: it's an expression.
mine(1);
The argument to mine has no name, it's not an expression, but a literal constant, represented by a compiler variable in the engine. It's similar to a temporary variable, a kind of constant expression.
mine($a);
The argument to mine has a name, which you can use to refer to it's value. It's a normal variable.
Only variables can be passed by reference because you cannot refer to expressions or literal constants
Next you need to understand why we pass-by-reference:
function mine(int $thing) {
$thing++;
}
$a = 1;
mine($a);
var_dump($a); // int(1)
In this code, $a is passed to mine() by value, so that the changes that mine() make to $thing are only visible inside the scope of mine. $a is unchanged after the call to mine() returns because $a and $thing are distinct, having been passed-by-value, which means it's value was copied on to the call stack for the invocation of mine().
function mine(int &$thing) {
$thing++;
}
$a = 1;
mine($a);
var_dump($a); // int(2)
In the code above, $a is passed to mine() by reference, this means that $a and $thing are no longer distinct. The changes mine() make to $thing are now visible after the call to mine() returns.
The last piece in the puzzle is Reflection:
function mine(int &$thing) {
$thing++;
}
$a = 1;
$reflector = new ReflectionFunction("mine");
$reflector->invoke($a);
The code above will raise:
Warning: Parameter 1 to mine() expected to be a reference, value given in /usr/src/php-src/refs.php on line 9
This is because ReflectionFunction::invoke and similar reflection functions (ReflectionClass::newInstance) accept their parameters by value and pass them onto the invoked function by value.
But ...
There is still a difference between pass-by-reference semantics, and passing by reference, a dangerous one:
class Foo {
public function qux() {}
}
class Bar {}
function mine(Foo &$foo) {
$foo = new Bar();
}
$foo = new Foo;
mine($foo);
$foo->qux();
Will obviously yield:
PHP Fatal error: Uncaught Error: Call to undefined method Bar::qux() in /usr/src/php-src/refs.php:16
Stack trace:
#0 {main}
thrown in /usr/src/php-src/refs.php on line 16
The declaration of mine() tells lies about the type safety of it's parameter. Type safety is only guaranteed upon entry to the function, the function body is free to break type safety, but it doesn't usually affect the caller when relying on the engines pass by reference semantics for objects.
This is an extremely scary kind of API, that should be avoided.
I am experimenting with using JNLua's javavm module to connect with and extend a Java library (JAR). So far I am super impressed with how easy it is to pass Java objects back and forth between Lua and Java- seemlessness.
Now I am interested to extend these Java objects in LUA. In my naive approach I've wrapped the Java object in a Lua class with the intent of extending that objects API i.e. adding methods to it. But I don't want to have to recreate, within the wrapper, all of the Java objects methods. It seems like I should be able to inherit from the Java object so that when a method is missing from my wrapper Lua will look for it in the Java object which is a member of the wrapped class. I've tried adapting the examples shown in Inheritance but this is a slightly trickier thing to set up, given that I'm dealing with a Java object. Thoughts?
I found my answer in the below SO question
Add members dynamically to a class using Lua + SWIG
I needed to realize I was dealing with a UserData object, not a table- no way to add members
I needed some metatable kung-fu
The below code has the effect of allowing me to extend (add methods) a Java object.
function Model:new (model)
o = {}
WrapObject(Model, o, model)
self.__index = self
self.model = model or nil
return o
end
function WrapObject(class, object, userData)
local wrapper_metatable = {}
function wrapper_metatable.__index(self, key)
local ret = rawget(class, key)
if(not ret) then
ret = userData[key]
if(type(ret) == "function") then
return function(self, ...)
return ret(userData, ...)
end
else
return ret
end
else
return ret
end
end
setmetatable(object, wrapper_metatable)
return object
end
function Model:Test ()
name = self:GetFullName()
fileName = self:GetFileName()
ret = name .. fileName
print("It's a test!!")
return ret
end
In order to instantiate a type like x = MyType{Int}()
I can define a inner constructor.
immutable MyType{T}
x::Vector{T}
MyType() = new(T[])
end
Is it possible to achieve the same objective using an outer constructor?
This can be done using the following syntax:
(::Type{MyType{T}}){T}() = MyType{T}(T[])
The thing in the first set of parentheses describes the called object. ::T means "of type T", so this is a definition for calling an object of type Type{MyType{T}}, which means the object MyType{T} itself. Next {T} means that T is a parameter of this definition, and a value for it must be available in order to call this definition. So MyType{Int} matches, but MyType doesn't. From there on, the syntax should be familiar.
This syntax is definitely a bit fiddly and unintuitive, and we hope to improve it in a future version of the language, hopefully v0.6.
I may be wrong, but if you cannot build parameterless function like this:
julia> f{T}() = show(T)
WARNING: static parameter T does not occur in signature for f at none:1.
The method will not be callable.
f (generic function with 1 method)
therefore you won't be able to do this:
julia> immutable MyType{T}
x::Vector{T}
end
julia> MyType{T}() = MyType{T}(T[])
WARNING: static parameter T does not occur in signature for call at none:1.
The method will not be callable.
MyType{T}
julia> x = MyType{Int}()
ERROR: MethodError: `convert` has no method matching convert(::Type{MyType{Int64}})
...
Every outer constructor is also a function.
You can say
f(T::Type) = show(T)
and also
MyType(T::Type) = MyType(T[])
But julia needs to see the type in the call to know which you want.
I'm trying to figure out how to instantiate a case class object with reflection. Is there any support for this? The closest I've come is looking at scala.reflect.Invocation, but this seems more for executing methods that are a part of an object.
case class MyClass(id:Long, name:String)
def instantiate[T](className:String)(args:Any*) : T = { //your code here }
Is close to the API I'm looking for.
Any help would be appreciated.
scala> case class Foo(id:Long, name:String)
defined class Foo
scala> val constructor = classOf[Foo].getConstructors()(0)
constructor: java.lang.reflect.Constructor[_] = public Foo(long,java.lang.String)
scala> val args = Array[AnyRef](new java.lang.Integer(1), "Foobar")
args: Array[AnyRef] = Array(1, Foobar)
scala> val instance = constructor.newInstance(args:_*).asInstanceOf[Foo]
instance: Foo = Foo(1,Foobar)
scala> instance.id
res12: Long = 1
scala> instance.name
res13: String = Foobar
scala> instance.getClass
res14: java.lang.Class[_] = class Foo
Currently there is not much reflection support in Scala. But you can fall back to th Java Reflection API. But there are some obstacles:
You have to create a Array[AnyRef] and box your "primitive types" in the wrapper classes (java.lang.Integer, java.lang.Character, java.lang.Double, ...)
newInstance(Object ... args) gets an varargs array of Object, so you should give the type inferer a hint with :_*
newInstance(...) returns an Object so you have to cast it back with asInstanceOf[T]
The closest I could get to your instantiate function is this:
def instantiate(clazz: java.lang.Class[_])(args:AnyRef*): AnyRef = {
val constructor = clazz.getConstructors()(0)
return constructor.newInstance(args:_*).asInstanceOf[AnyRef]
}
val instance = instantiate(classOf[MyClass])(new java.lang.Integer(42), "foo")
println(instance) // prints: MyClass(42,foo)
println(instance.getClass) // prints: class MyClass
You cannot get the get class from a generic type. Java erases it (type erasure).
Edit: 20 September 2012
Three years on, the instantiate method can be improved to return a properly typed object.
def instantiate[T](clazz: java.lang.Class[T])(args:AnyRef*): T = {
val constructor = clazz.getConstructors()(0)
return constructor.newInstance(args:_*).asInstanceOf[T]
}
See http://www.nabble.com/How-do-I-get-the-class-of-a-Generic--td20873455.html
See answers to Scala: How do I dynamically instantiate an object and invoke a method using reflection? as well, especially regarding type erasure.
This is what I've ended up with so far, I'd like to not have to deal directly with AnyRef if possible. So if anyone knows a way to get around that I'd appreciate the help.
case class MyClass(id:Long,name:String)
def instantiate[T](classArgs: List[AnyRef])(implicit m : Manifest[T]) : T ={
val constructor = m.erasure.getConstructors()(0)
constructor.newInstance(classArgs:_*).asInstanceOf[T]
}
val list = List[AnyRef](new java.lang.Long(1),"a name")
val result = instantiate[MyClass](list)
println(result.id)