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)
Related
I am new to Kotlin and am still trying to learn it. I have been researching this problem for several hours now and still have not figured it out. I want to get an element from inside of a list by it's index. I figured out how to do this with a plain list, like so
val my_list = listOf(1,2,3)
println(my_list.get(0))
The above works, but when I try to do this with a list that is stored inside of a map
val my_list = mutableMapOf<String, Any>()
my_list["set1"] = listOf(1,2,3)
my_list["set2"] = listOf("A","B","C")
my_list["set3"] = listOf("d","e","f")
val sub_list = my_list["set1"]
println(sub_list.get(0))
I get the following error
Unresolved reference. None of the following candidates is applicable
because of receiver type mismatch: #InlineOnly public inline operator
fun <#OnlyInputTypes K, V> Map.get(key: Int): ???
defined in kotlin.collections #SinceKotlin public operator fun
MatchGroupCollection.get(name: String): MatchGroup? defined in
kotlin.text
Note: I primarily use Python, so that is what I am used to. The functionality from Python that I am trying to reproduce in Kotlin is having a dictionary of lists.
The problem is the type declaration of your map, it should be:
val my_list = mutableMapOf<String, List<Any>>()
Any doesn't have a get() method, so there's no way to invoke it.
Even when that problem is solved, you'll probably have to deal with nullability, though, as:
val sub_list = my_list["set1"]
Will return List<Any>?, which means that my_list might not have a value for the specified key. If that's the case, you'll have to do something like:
sub_list?.get(0)?.run { println(it) }
Which in turn, could also cause an exception if the sub_list is empty. That could be solved with something more like:
vsub_list?.firstOrNull()?.run { println(it) }
Beginner in Kotlin here.
I try to create and populate objects by reflection in a program. I cannot find the equivalent functionality in pure kotlin so my solution resembles the code below which works fine, but requires the use of dirty references like java.lang.String::class.java and intelliJ, understandably, doesn't seem to like this. Is there a simpler way that I am missing to do this?
val jclass = myObject::class.java
val setters = jclass.declaredMethods.filter { it.name.startsWith("set") }
for (s in setters) {
val paramType = s.parameterTypes.first()
val data = when(paramType) {
java.lang.Integer::class.java -> foo
java.lang.Double::class.java -> bar
java.lang.String::class.java -> baz
}
s.invoke(myObject, data)
}
You can use Kotlin reflection, which requires you to add kotlin-reflect as a dependency to your project.
Here you can find kotlin-reflect for Kotlin 1.0.5, or pick another version if you use different Kotlin version.
After that, you can rewrite your code as follows:
val properties = myObject.javaClass.kotlin.memberProperties
for (p in properties.filterIsInstance<KMutableProperty<*>>()) {
val data = when (p.returnType.javaType) {
Int::class.javaPrimitiveType,
Int::class.javaObjectType -> foo
Double::class.javaPrimitiveType,
Double::class.javaObjectType -> bar
String::class.java -> baz
else -> null
}
if (data != null)
p.setter.call(myObject, data)
}
Some details:
Despite using Kotlin reflection, this approach works with Java classes as well, their fields and accessors will be seen as properties, as described here.
Just like with Java reflection, memberProperties returns public properties of this type and all its supertypes. To get all the properties declared in the type (including the private ones, but not those from the supertypes), use declaredMemberProperties instead.
.filterIsInstance<KMutableProperty<*> returns only the mutable properties, so that you can use their p.setter later. If you need to iterate over the getters of all the properties, remove it.
In the when block, I compared p.returnType.javaType to Int::class.javaPrimitiveType and Int::class.javaObjectType, because what's Int in Kotlin can be mapped to either Java int or java.lang.Integer depending on its usage. In Kotlin 1.1, it will be enough to check p.returnType.classifier == Int::class.
If You need to get property getter/setter, there is a couple of built-in constructions for it YourClass::propertyName
have a look at example bellow
fun main(args: Array<String>) {
val myObject = Cat("Tom", 3, 35)
println(Cat::age.getter.call(myObject)) // will print 3
Cat::age.setter.call(myObject, 45)
print(myObject) // will print Cat(name=Tom, age=45, height=35)
}
data class Cat(var name : String, var age : Int, val height : Int)
but sometimes you don't know class exactly(working with generics) or need to get list of properties, then use val <T : Any> KClass<T>.declaredMemberProperties: Collection<KProperty1<T, *>> it will return all properties, some of them can be mutable(var) and some immutable(val), you can find out immutability by checking belonging to KMutableProperty<*> (by filtering with is operator or using convenience methods such as filterIsInstance<KMutableProperty<*>>)
about your code snippet
I absolutely agree with hotkey, but now it is better to use myObject::class.declaredMemberProperties instead of myObject.javaClass.kotlin.memberProperties
because the second one is deprecated
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/java-class.html
data class Cat(var name : String, var age : Int, val height : Int)
#JvmStatic
fun main(args: Array<String>) {
val myObject = Cat("Tom", 3, 35)
val properties = myObject::class.declaredMemberProperties
for (p in properties.filterIsInstance<KMutableProperty<*>>()) {
val data = when (p.returnType.javaType) {
Int::class.javaPrimitiveType,
Int::class.javaObjectType -> 5
String::class.java -> "Rob"
else -> null
}
if (data != null)
p.setter.call(myObject, data)
}
println(myObject)
// it will print Cat(name=Rob, age=5, height=35),
// because height isn't var(immutable)
}
in general, I would approach similar problems with such construction in mind
val myObject = Cat("Tom", 3, 35)
Cat::class.declaredMemberProperties
//if we want only public ones
.filter{ it.visibility == KVisibility.PUBLIC }
// We only want strings
.filter{ it.returnType.isSubtypeOf(String::class.starProjectedType) }
.filterIsInstance<KMutableProperty<*>>()
.forEach { prop ->
prop.setter.call(myObject, "Rob")
}
println(myObject)
//it will print Cat(name=Rob, age=3, height=35),
//because name is only eligible in this case
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
I am trying to do this:
var dictArray = [String:[String]]()
dictArray["test"] = [String]()
dictArray["test"]! += "hello"
But I am getting the weird error NSString is not a subtype of 'DictionaryIndex<String, [(String)]>'.
I just want to be able to add objects to an array inside a dictionary.
Update: Looks like Apple considers this a "known issue" in Swift, implying it will work as expected eventually. From the Xcode 6 Beta 4 release notes:
...Similarly, you cannot modify the underlying value of a mutable
optional value, either conditionally or within a force-unwrap:
tableView.sortDescriptors! += NSSortDescriptor(key: "creditName", ascending: true)
Workaround: Test the optional value explicitly and then assign the
result back:
if let window = NSApplication.sharedApplication.mainWindow {
window.title = "Currently experiencing problems"
}
tableView.sortDescriptors = tableView.sortDescriptors!
You can only do this
var dictArray = [String:[String]]()
dictArray["test"] = [String]()
var arr = dictArray["test"]!;
arr += "hello"
dictArray["test"] = arr
because dictArray["test"] give you Optional<[String]> which is immutable
6> var test : [String]? = [String]()
test: [String]? = 0 values
7> test += "hello"
<REPL>:7:1: error: '[String]?' is not identical to 'UInt8'
append also won't work due to the same reason, Optional is immutable
3> dictArray["test"]!.append("hello")
<REPL>:3:18: error: '(String, [(String)])' does not have a member named 'append'
dictArray["test"]!.append("hello")
^ ~~~~~~
BTW the error message is horrible...
You may use NSMutableArray instead of [String] as a value type for your dictionary:
var dictArray: [String: NSMutableArray] = [:]
dictArray["test"] = NSMutableArray()
dictArray["test"]!.addObject("hello")
This is still an issue in Swift 3. At least I was able to create method that can handle it for you.
func appendOrCreate(newValue: Any, toArrayAt key: String, in existingDictionary: inout [AnyHashable:Any]) {
var mutableArray = [Any]()
if let array = existingDictionary[key] as? [Any]{
//include existing values in mutableArray before adding new value
for existingValue in array {
mutableArray.append(existingValue)
}
}
//append new value
mutableArray.append(newValue)
//save updated array in original dictionary
existingDictionary[key] = mutableArray
}
The problem is that we want class semantics here but have to use structs. If you put class objects into the dictionary, you get what you want!
So, if you haveĀ¹ to have mutable values, you can wrap them in a class and perform updates with a closure:
class MutableWrapper<T> {
var rawValue: T
init(_ val: T) {
self.rawValue = val
}
func update(_ with: (inout T) -> Void) {
with(&self.rawValue)
}
}
Example:
func foo() {
var dict = [String: MutableWrapper<[String]>]()
dict["bar"] = MutableWrapper(["rum"])
dict["bar"]?.update({$0.append("gin")})
print(dict["bar"]!.rawValue)
// > ["rum", "gin"]
}
For what it's worth, I do not see a way to keep caller and wrapper in sync. Even if we declare init(_ val: inout T) we will end up with a copy in rawValue.
Performance is not necessarily an issue since the compiler optimizes structs heavily. I'd benchmark any mutable solution against what looks like lots of copy-updates in the code.
Since Swift 4.1 you can provide a default value to the subscript which allows you to solve this quite naturally now:
dictArray["test", default: []].append("hello")
When I research a new library, I sometimes find it hard to locate the implementation of a method.
In Java, Metho#getDeclaringClass provides the class that declared a given method. So by iterating over Class#getMethods, I can find for each method, the class that declared it.
In Scala, traits are converted to Java interfaces and a class that extends a trait will implement the methods of the trait by forwarding them to a companion class defining these methods statically. This means, that Method#getDeclaringClass will return the class, not the trait:
scala> trait A { def foo = {println("hi")}}
defined trait A
scala> class B extends A
defined class B
scala> classOf[B].getMethods.find(_.getName() == "foo").get.getDeclaringClass
res3: java.lang.Class[_] = class B
What is the best way to work around this? Meaning, given a class, how can I get a List[(Method, Class)] where each tuple is a method and the trait/class it was declared in?
In Scala 2.8 you can use the ScalaSigParser to parse the scala specific byte code information.
This will be more stable than the byte code serialization format of scala traits, classes and methods.
import tools.scalap.scalax.rules.scalasig._
import scala.runtime._
val scalaSig = ScalaSigParser.parse(classOf[RichDouble]).get
val richDoubleSymbol = scalaSig.topLevelClasses.head
val methods = richDoubleSymbol.children filter ( _ match {
case m : MethodSymbol => true
case _ => false
})
methods foreach println
richDoubleSymbol.isTrait
ScalaSigParser.parse(classOf[Ordered[Any]]).get.topLevelClasses.head.isTrait
Prints:
scala> methods foreach println
MethodSymbol(x, owner=0, flags=20080004, info=23 ,None)
MethodSymbol(<init>, owner=0, flags=200, info=33 ,None)
[...]
MethodSymbol(isPosInfinity, owner=0, flags=200, info=117 ,None)
MethodSymbol(isNegInfinity, owner=0, flags=200, info=117 ,None)
scala> richDoubleSymbol.isTrait
res1: Boolean = false
scala> ScalaSigParser.parse(classOf[Ordered[Any]]).get.topLevelClasses.head.isTrait
res2: Boolean = true
I suppose following this road you can build a reflection API for Scala.
Here's something that sort-of-works:
def methods(c: Class[_]): Array[String] = {
val dm = try {
val cls = if (c.isInterface) Class.forName(c.getName() + "$class") else c
cls.getDeclaredMethods().map(m =>
decode(c.getCanonicalName) + "#" +
decode(m.getName) + "(" +
{m.getParameterTypes.toList match {
case h :: tail => tail.map{(c: Class[_]) => decode(c.getCanonicalName)}.mkString(",")
case Nil => ""
}} + "): " +
decode(m.getReturnType.getCanonicalName))
} catch {case _ => Array[String]()}
dm ++ c.getInterfaces.flatMap(methods(_))
}
scala> trait A {def hi = {println("hi")}}
scala> class B extends A
scala> methods(classOf[B]).foreach(println(_))
Main.$anon$1.B#$tag(): int
Main.$anon$1.B#Main$$anon$A$$$outer(): Main.$anon$1
Main.$anon$1.B#Main$$anon$B$$$outer(): Main.$anon$1
Main.$anon$1.B#hi(): void
Main.$anon$1.A#$init$(): void
Main.$anon$1.A#hi(): void
scala.ScalaObject#$tag(): int
scala.ScalaObject#$init$(): void
You can see there's some filtering that can be done and maybe some conversions.
The most annoying thing is that B has a declaration of 'hi', because it forwards the call to A$class#hi. However, this is indistinguishable from the case where B actually overrides 'hi' with its own implementation.
If your goal is actually "research[ing] a new library," the documentation gives you this information. Inherited methods (not overridden) are listed and linked (their names only) under the inherited class that defines them.
Is this not sufficient for the purposes of understanding the libary? Also, each documentation page includes a link to the source code.