How can I use reflection on package-level functions, members, etc.? Trying to access javaClass or class doesn't work, neither does package.
Reflection on top level functions or properties is not yet supported in Kotlin but is planned for the future. The only features that are supported at the moment allow you to obtain Kotlin reflection objects corresponding to the given Java reflection objects, requiring you to use Java reflection beforehand:
kotlinFunction returns a kotlin.reflect.KFunction instance by a java.lang.reflect.Method instance or by a java.lang.reflect.Constructor instance
kotlinProperty returns a kotlin.reflect.KProperty instance by a java.lang.reflect.Field instance
To use them, you must first obtain the corresponding method or field with the Java reflection:
package a
import kotlin.reflect.jvm.*
fun foo() {}
fun reflectFoo() {
// a.TestKt is the JVM class name for the file test.kt in the package a
val c = Class.forName("a.TestKt")
val m = c.getDeclaredMethod("foo")
val f = m.kotlinFunction!!
// f is a KFunction instance, so you can now inspect its parameters, annotations, etc.
println(f.name)
println(f.returnType)
...
}
Related
I'm experimenting with the reflection functionality in Kotlin, but I can't seem to understand how to obtain a KType value.
Suppose I have a class that maps phrases to object factories. In case of ambiguity, the user can supply a type parameter that narrows the search to only factories that return that type of object (or some sub-type).
fun mapToFactory(phrase: Phrase,
type: KType = Any::class): Any {...}
type needs to accept just about anything, including Int, which from my experience seems to be treated somewhat specially. By default, it should be something like Any, which means "do not exclude any factories".
How do I assign a default value (or any value) to type?
From your description, sounds like your function should take a KClass parameter, not a KType, and check the incoming objects with isSubclass, not isSubtype.
Types (represented by KType in kotlin-reflect) usually come from signatures of declarations in your code; they denote a broad set of values which functions take as parameters or return. A type consists of the class, generic arguments to that class, and nullability. The problem with types at runtime on JVM is that because of erasure, it's impossible to determine the exact type of a variable of a generic class. For example if you have a list, you cannot determine the generic type of that list at runtime, i.e. you cannot differentiate between List<String> and List<Throwable>.
To answer your initial question though, you can create a KType out of a KClass with createType():
val type: KType = Any::class.createType()
Note that if the class is generic, you need to pass type projections of generic arguments. In simple cases (all type variables can be replaced with star projections), starProjectedType will also work. For more info on createType and starProjectedType, see this answer.
Since Kotlin 1.3.40, you can use the experimental function typeOf<T>() to obtain the KType of any type:
val int: KType = typeOf<Int>()
In contrast to T::class.createType(), this supports nested generic arguments:
val listOfString: KType = typeOf<List<String>>()
The typeOf<T>() function is particularly useful when you want to obtain a KType from a reified type parameter:
inline fun <reified T> printType() {
val type = typeOf<T>()
println(type.toString())
}
Example usage:
fun main(args: Array<String>) {
printType<Map<Int, String>>()
// prints: kotlin.collections.Map<kotlin.Int, kotlin.String>
}
Since this feature is still in experimental status, you need to opt-in with #UseExperimental(ExperimentalStdlibApi::class) around your function that uses typeOf<T>(). As the feature becomes more stable (possibly in Kotlin 1.4), this can be omitted. Also, at this time it is only available for Kotlin/JVM, not Kotlin/Native or Kotlin/JS.
See also:
Release announcement
API Doc (very sparse currently)
I've been wondering how delegated properties ("by"-Keyword) work under-the-hood. I get that by contract the delegate (right side of "by") has to implement a get and setValue(...) method, but how can that be ensured by the compiler and how can those methods be accessed at runtime? My initial thought was that obviously the delegates must me implementing some sort of "SuperDelegate"-Interface, but it appears that is not the case. So the only option left (that I am aware of) would be to use Reflection to access those methods, possibly implemented at a low level inside the language itself. I find that to be somewhat weird, since by my understanding that would be rather inefficient. Also the Reflection API is not even part of the stdlib, which makes it even weirder.
I am assuming that the latter is already (part of) the answer. So let me furthermore ask you the following: Why is there no SuperDelegate-Interface that declare the getter and setter methods that we are forced to use anyway? Wouldn't that be much cleaner?
The following is not essential to the question
The described Interface(s) are even already defined in ReadOnlyProperty and ReadWriteProperty. To decide which one to use could then be made dependable on whether we have a val/var. Or even omit that since calling the setValue Method on val's is being prevented by the compiler and only use the ReadWriteProperty-Interface as the SuperDelegate.
Arguably when requiring a delegate to implement a certain interface the construct would be less flexible. Though that would be assuming that the Class used as a Delegate is possibly unaware of being used as such, which I find to be unlikely given the specific requirements for the necessary methods. And if you still insist, here's a crazy thought: Why not even go as far as to make that class implement the required interface via Extension (I'm aware that's not possible as of now, but heck, why not? Probably there's a good 'why not', please let me know as a side-note).
The delegates convention (getValue + setValue) is implemented at the compiler side and basically none of its resolution logic is executed at runtime: the calls to the corresponding methods of a delegate object are placed directly in the generated bytecode.
Let's take a look at the bytecode generated for a class with a delegated property (you can do that with the bytecode viewing tool built into IntelliJ IDEA):
class C {
val x by lazy { 123 }
}
We can find the following in the generated bytecode:
This is the field of the class C that stores the reference to the delegate object:
// access flags 0x12
private final Lkotlin/Lazy; x$delegate
This is the part of the constructor (<init>) that initialized the delegate field, passing the function to the Lazy constructor:
ALOAD 0
GETSTATIC C$x$2.INSTANCE : LC$x$2;
CHECKCAST kotlin/jvm/functions/Function0
INVOKESTATIC kotlin/LazyKt.lazy (Lkotlin/jvm/functions/Function0;)Lkotlin/Lazy;
PUTFIELD C.x$delegate : Lkotlin/Lazy;
And this is the code of getX():
L0
ALOAD 0
GETFIELD C.x$delegate : Lkotlin/Lazy;
ASTORE 1
ALOAD 0
ASTORE 2
GETSTATIC C.$$delegatedProperties : [Lkotlin/reflect/KProperty;
ICONST_0
AALOAD
ASTORE 3
L1
ALOAD 1
INVOKEINTERFACE kotlin/Lazy.getValue ()Ljava/lang/Object;
L2
CHECKCAST java/lang/Number
INVOKEVIRTUAL java/lang/Number.intValue ()I
IRETURN
You can see the call to the getValue method of Lazy that is placed directly in the bytecode. In fact, the compiler resolves the method with the correct signature for the delegate convention and generates the getter that calls that method.
This convention is not the only one implemented at the compiler side: there are also iterator, compareTo, invoke and the other operators that can be overloaded -- all of them are similar, but the code generation logic for them is simpler than that of delegates.
Note, however, that none of them requires an interface to be implemented: the compareTo operator can be defined for a type not implementing Comparable<T>, and iterator() does not require the type to be an implementation of Iterable<T>, they are anyway resolved at compile-time.
While the interfaces approach could be cleaner than the operators convention, it would allow less flexibility: for example, extension functions could not be used because they cannot be compiled into methods overriding those of an interface.
If you look at the generated Kotlin bytecode, you'll see that a private field is created in the class holding the delegate you're using, and the get and set method for the property just call the corresponding method on that delegate field.
As the class of the delegate is known at compile time, no reflection has to happen, just simple method calls.
Similar questions have been raised multiple times, but I'm focussing on the namespace and pointer issues.
MyClass.h
namespace foo {
class MyClass {
MyClass();
};
QDataStream &operator<<(QDataStream &out, const MyClass & myObj);
QDataStream &operator>>(QDataStream &in, MyClass &myObj);
} // namespace foo
Q_DECLARE_METATYPE(foo::MyClass) // #1
Q_DECLARE_METATYPE(foo::MyClass*) // #2
fooMyClass.cpp (so many permutations):
MyClass::MyClass()
{
qRegisterMetaType<MyClass>("MyClass"); // #3
qRegisterMetaType<MyClass*>("MyClass*"); // #4
qRegisterMetaType<MyClass>("foo::MyClass"); // #5
qRegisterMetaType<MyClass*>("foo::MyClass*"); // #6
qRegisterMetaType<foo::MyClass>("foo::MyClass"); // #7
qRegisterMetaType<foo::MyClass*>("foo::MyClass*"); // #8
qRegisterMetaType<MyClass>(); // #9
qRegisterMetaType<MyClass*>(); // #10
qRegisterMetaType<foo::MyClass>(); // #11
qRegisterMetaType<foo::MyClass*>(); // #12
// same for qRegisterMetaTypeStreamOperators<T>();
}
So my question is, when and why is it required to provide the namespace and/or the pointer variant if I intend to use the custom objects for signals and slots (potentially as reference and pointer) inside as well as outside the namespace. Do I always have to fully qualify the namespace?
I'm referring to Qt5 in this answer. Qt4 doesn't go well with this use case.
Data stream operators
Data stream operators are not required for your type if you only intend to use it in signals and slots. They are required if you want to do some serialization.
Pointers, references and values
Qt considers MyClass and MyClass* two different unrelated types. You should declare, register and use them separately. Using const MyClass & argument type is compatible with MyClass in Qt meta-object system. Note that using MyClass and MyClass* meta types simultaneously in one program is unusual and can cause mistakes and confusion. You should choose one of the options and use it throughout the program. Also passing pointers to slots is not recommended because it causes unsolvable ownership problem. So I recommend to use passing by const reference (which sometimes will be converted to passing by value internally in Qt signal-slot system). If MyClass objects contain massive data, you should implement implicit data sharing using QSharedDataPointer.
Declaring a meta type
First of all, you always need to declare your meta type:
Q_DECLARE_METATYPE(foo::MyClass)
It works at compile time, so there are no limitations on how you refer to your class. The following code will work as well:
using namespace foo;
Q_DECLARE_METATYPE(MyClass)
Registering a meta type
Now you need to register your classes. Theoretically, you need to specify all strings that you want to use to refer to your type, i.e.:
qRegisterMetaType<foo::MyClass>("MyClass");
qRegisterMetaType<foo::MyClass>("foo::MyClass");
It doesn't matter how you refer to MyClass in the template argument. The following code will work similarly:
using namespace foo;
qRegisterMetaType<MyClass>("MyClass");
qRegisterMetaType<MyClass>("foo::MyClass");
For example, the "MyClass" and "foo::MyClass" strings are used to identify argument types when you refer to your signals and slots like SIGNAL(signal1(MyClass)).
New signal and slot syntax
If you using new signal slot syntax with pointers to member functions, you need to do only one registration with arbitrary string argument. It seems that it is intended to make it work even without any registrations. This part of the docs instructs to only add Q_DECLARE_METATYPE, in opposite to this that requires qRegisterMetaType(). Unfortunately, now in my Qt installation it works only with direct connections. Queued connections still require at least one registration call.
Implicit registration of class without namespace
I was experimenting with some variants of registration in Qt 5.1 and found out that Qt automatically registers aliases without namespace. So if you write
qRegisterMetaType<foo::MyClass>("foo::MyClass");
, Qt will additionally automatically register "MyClass" alias. So, after executing this statement you will be able to refer to your type as MyClass and foo::MyClass. There is no information in the documentation about how Qt handles namespaces. We could assume that this behavior is intended and will not be removed in next versions but I wouldn't rely on that. The following code makes implicit registration obvious:
qRegisterMetaType<foo::MyClass>("foo::MyClass");
qRegisterMetaType<bar::MyClass>("MyClass");
Qt 5.1 says:
QMetaType::registerTypedef: Binary compatibility break -- Type name 'MyClass' previously registered as typedef of 'MyClass' [1030], now registering as typedef of 'bar::MyClass' [1032].
Qt 4.8 works without error (it seems that this behavior is not yet introduced in this version).
I am writing a DSL for expressing flow (original I know) in groovy. I would like to provide the user the ability to write functions that are stored and evaluated at certain points in the flow. Something like:
states {
"checkedState" {
onEnter {state->
//do some groovy things with state object
}
}
}
Now, I am pretty sure I could surround the closure in quotes and store that. But I would like to keep syntax highlighting and content assist if possible when editing these DSLs. I realize that the closure COULD reference artifacts from the surrounding flow definition which would no longer be valid when executing the closure in a different context, and I am fine with this. In reality I would like to use the closure syntax for a non-closure function definition.
tl;dr; I need to get the closure's code while evaluating the DSL so that it can be stored in the database and executed by a script host later.
I don't think there is a way to get a closure's source code, as this information is discarded during compilation. Perhaps you could try writing an AST transformation that would make closure's syntax tree available at runtime.
If all you care about is storing the closure in the database, and you don't need later access to the source code, you can try serializing it and storing the serialized form.
Closure implements Serializable, and after nulling its owner, thisObject and delegate attributes I was able to serialize it, but I'm getting ClassNotFoundException on deserialization.
def myClosure = {a, b -> a + b}
Closure.metaClass.setAttribute(myClosure, "owner", null)
Closure.metaClass.setAttribute(myClosure, "thisObject", null)
myClosure.delegate = null
def byteOS = new ByteArrayOutputStream()
new ObjectOutputStream(byteOS).writeObject(myClosure)
def serializedClosure = byteOS.toByteArray()
def input = new ObjectInputStream(new ByteArrayInputStream(serializedClosure))
def deserializedClosure = input.readObject() // throws CNFE
After some searching, I found Groovy Remote Control, a library created specifically to enable serializing closures and executing them later, possibly on a remote machine. Give it a try, maybe that's what you need.
Does anyone know the status of a fully-featured reflection API for Scala?
I know that you can use Java's reflection API to do simple things but this does not work well with Scala's language features. I found an interesting article describing an experimental Scala Mirroring API but as far as I know this is still experimental. I've also found mention of a ScalaSigParser but this seems to be pretty low level.
This is more of a curiosity than anything else as I am currently just playing around with Scala. I thought that the answer to this question might also be useful to others interested in Scala.
The "immutable replacement for the JavaBean style pattern" can be expressed named parameters and optionally the #BeanProperty annotation:
import reflect._
case class A(#BeanProperty val x: String, #BeanProperty val y : Int)
A(x = "s", y = 3)
A(y = 3, x = "s")
Adding methods (more precise: defining a new interface) makes only sense in a statically typed language if the client knowns about the new methods and can compile against the interface. With structural typing clients can define methods they expect to be present in an object. The Scala compiler will transform the structural type into reflection code which may fail at runtime.
type T = {def go(x : Int): Int }
def y(any : Any) = any.asInstanceOf[T].go(2)
class A{
def go(x : Int) = x + 1
}
y(new A())
y(new {}) //this will fail
You can define new classes or traits with the interpreter on the fly. The Interpret method transforms Scala code to byte code.
You've already mentioned the ScalaSigParser which is not exactly easy to work with.
I think the rest of features you like are not there yet.