Is there a way to use an annotation class as a decorator on a function in Kotlin? - kotlin

I am very new to Kotlin development and I came across custom annotation classes in the documentation.
Is there a way for me to use an annotation on a function as a way to pre-populate some variables, or to run a decorator function before running the annotated function?
Something like:
class TestClass {
#Friendly("Hello World")
private fun testFun() {
greet()
//does something else
}
}
with an annotation class like
#Target(AnnotationTarget.FUNCTION)
#Retention(AnnotationRetention.BINARY)
annotation class Friendly(val message: String) {
fun greet() {
println(message)
}
}
I know this isn't valid Kotlin code, but I can't find any examples on how to actually use values from annotations without using reflection (if it's even possible)
Please let me know if I can do something like this, and more usefully, a better resource on annotation classes for Kotlin?

To make use of your custom annotations, you need to either create your own annotation processor (and use kapt Kotlin compiler plugin) to generate some new sources (but not modify existing!) at compile time, or use #Retention(AnnotationRetention.RUNTIME) meta-annotation (which is default in Kotlin), so that they could be accessed via reflection in runtime.
#Retention(AnnotationRetention.BINARY) meta-annotation you're using is equivalent of #Retention(RetentionPolicy.CLASS) in java, which is mostly useless (see https://stackoverflow.com/a/5971247/13968673).
What you're trying to do with annotations (call some additional code before/after method execution) reminds me aspect-oriented programming. Take a look at Spring AOP and AspectJ frameworks, following this paradigm, and their approach for annotations processing. TL;DR: Spring AOP is processing annotations in runtime, generating proxy-classes with respectful code, while AspectJ is using its own compiler (even not an annotation processor, cause it also introduces its own syntactic extension for java language), and can generate respectful bytecode at compile-time. They both are originally java-oriented, but with some configurational pain could be used with Kotlin too.

Related

Is the jvm method name of function with inline classes stable?

I declared an inline class
#JvmInline
value class Creator<T>(val type: KClass<T>);
, and declared an interface
interface Itf {
fun <T> creator(type: KClass<T>): Creator<T>;
}
I want to implement this interface by generating the bytecode by asm(https://asm.ow2.io/ 1).
I found java method decompiled from bytecode is
public KClass<T> creator-9k1ZQyY();
The java method name is “creator-9k1ZQyY”. the suffix “-9k1ZQyY” is added by kotlin compiler and I know why kotlin compiler did it.
This suffix is very important for bytecode generator.
My question:
If the interface and inline class are stable, can kotlin compiler guarantee that suffix is stable too? Does that suffix have nothing to do with the version of kotlin-compiler?
The docs seem to suggest the mangling is stable:
functions using inline classes are mangled by adding some stable hashcode to the function name
As noted in the same doc, the mangling scheme has changed once with the version 1.4.30 of the Kotlin compiler, but I would consider it quite stable nonetheless. They even provided a flag to use the old scheme to generate binary compatible code, so I'm assuming it's not only unlikely to change again, but even if it does, it will surely be done with some way to keep compatibility.

what is the benefit of extension fun in kotlin?Is it good to leak a fun to other classes?

Is it a good idea to cut my code anywhere around the project in other classes using extension functions?
I mean what is the point?For what exactly a class fun can leak to other classes?
Friends, I'm new to Kotlin and I appreciate if anyone can provide a real example of using extension fun in kotlin.
class Car{
//any code you imagine
}
class Garage{
//any code
fun Car.boost(){
//boost implementation
}
}
As stated in Kotlin Coding Conventions, extension functions are a good practice:
Use extension functions liberally. Every time you have a function that
works primarily on an object, consider making it an extension function
accepting that object as a receiver.
There are a few reasons for that:
Extension functions keep your class small and easy to reason about
Extension functions force you to have good API, since they cannot access any private members of your class
Extension functions have zero cost on performance, since they're simply rewritten by Kotlin compiler into static methods, with method receiver (the class you're extending) as its first argument

Kotlin Reflection: How to know if a Kotlin class is marked with "internal" visibility modifier

I'm autogenerating code with KotlinPoet and Auto Service. I didn't find any way to know if an annotated class has "internal" modifier so I can create another class with same modifier. For example:
#MyAnnotation
internal class Car
So I thought using Kotlin Reflection I would be able to get this information but no luck.
With the annotator processor I'm able to get the KClass but the visibility said "public":
Any clues on how to do it?
Kotlin reflection is not applicable during annotation processing. Kotlin reflection is for inspecting your code at runtime.
However there is a way to parse the metadata out of Kotlin class files, it's called kotlinx-metadata-jvm.
To use this in your annotation processor, you'll have to obtain the AnnotationMirror of the kotlin.Metadata annotation. From that mirror, obtain the annotation values and use them to construct the KotlinClassHeader as you can see in the examples for kotlinx-metadata-jvm. Once you are there you can use kotlinx-metadata-jvm to extract the flags for your class.
Kotlin's KClass has the visibility property, which can be KVisibility.INTERNAL.
Since internal is a visibility modifier, you should look for something related in the KClass API. The following will help you:
/**
* Visibility of this class, or `null` if its visibility cannot be represented in Kotlin.
*/
#SinceKotlin("1.1")
public val visibility: KVisibility?
Used like this: Car::class.visibility //INTERNAL

Using default function implementation of interface in Kotlin

I have a Kotlin interface with a default implementation, for instance:
interface Foo {
fun bar(): String {
return "baz"
}
}
This would be okay until I try to implement this interface from Java. When I do, it says the class need to be marked as abstract or implement the method bar(). Also when I try to implement the method, I am unable to call super.bar().
Generating true default methods callable from Java is an experimental feature of Kotlin 1.2.40.
You need to annotate the methods with the #JvmDefault annotation:
interface Foo {
#JvmDefault
fun bar(): String {
return "baz"
}
}
This feature is still disabled by default, you need to pass the -Xjvm-default=enable flag to the compiler for it to work. (If you need to do this in Gradle, see here).
It really is experimental, however. The blog post warns that both design and implementation may change in the future, and at least in my IDE, Java classes are still marked with errors for not implementing these methods, despite compiling and working fine.
Please see the related issue.
There is a recommendation in the comments:
Write your interface in Java (with default methods) and both the Java and Kotlin classes correctly use those defaults
If you know you won't be overriding the function in any implementations of your interface, you can use extension functions as a nice workaround for this issue. Just put an extension function in the same file as the interface (and at the top level so other files can use it).
For example, what you're doing could be done this way:
interface Foo {
// presumably other stuff
}
fun Foo.bar(): String {
return "baz"
}
See the docs on extension functions for more information about them.
One "gotcha" worth noting:
We would like to emphasize that extension functions are dispatched statically, i.e. they are not virtual by receiver type. This means that the extension function being called is determined by the type of the expression on which the function is invoked, not by the type of the result of evaluating that expression at runtime.
Put simply, extension functions don't do what you might expect from regular polymorphism. What this means for this workaround is that the default function cannot be overridden like a regular function. If you try to override it, you'll get some weird behavior, because the "overridden" version will be called whenever you're dealing explicitly with the subclass, but the extension version will be called when you're dealing with the interface generically. For example:
interface MyInterface {
fun a()
}
fun MyInterface.b() {
println("MyInterface.b() default implementation")
}
class MyInterfaceImpl : MyInterface {
override fun a() {
println("MyInterfaceImpl.a()")
}
fun b() {
println("MyInterfaceImpl.b() \"overridden\" implementation")
}
}
fun main(args: Array<String>) {
val inst1: MyInterface = MyInterfaceImpl()
inst1.a()
inst1.b() // calls the "default" implementation
val inst2: MyInterfaceImpl = MyInterfaceImpl() // could also just do "val inst2 = MyInterfaceImpl()" (the type is inferred)
inst2.a()
inst2.b() // calls the "overridden" implementation
}
Since Kotlin 1.4.0, you can use one of the following compiler flags:
-Xjvm-default=all
-Xjvm-default=all-compatibility (for binary compatibility with old Kotlin code)
This will enable JVM default method compilation for all interfaces.
If you want to read up on how to set these flags in your IDE or Maven/Gradle project, check out the documentation on compiler options.
Progress on this is being tracked in issue KT-4779, which also includes a helpful summary of the current state. The #JvmDefault annotation and the older -Xjvm-default=enable and -Xjvm-default=compatibility compiler flags should no longer be used.
Unlike earlier version of Java8, Kotlin can have default implementation in interface.
When you implement Foo interface into a Java class. Kotlin hides those implementation of interface method. As stated here.
Arrays are used with primitive datatypes on the Java platform to avoid the cost of boxing/unboxing operations. As Kotlin hides those implementation details, a workaround is required to interface with Java code
This is specific for Arrays in above link but it also applies to all the classes (May be to give support for earlier version of Java8).
EDIT
Above explanation is opinion based.
One thing i came across and that is the main reason.
Kotlin binaries were compiled with java bytecode version 1.8 without default methods in interfaces. And they are facing critical issue solving it.

Is it possible to add "static" extension function for Java class?

For example I have Java class (from external library):
class A {} // This is Java class
I want to add extension functions written on Kotlin and call it as:
A.foo() // This is call of extension function `foo` from Kotlin code
As I understand, right now it is impossible to do in Kotlin because it support "static" extension functions for KClass-es with companion object only. Right?
Seems like nothing to prevent to implement such functionality in Kotlin later. Right?
UPDATE 2019-06-12: This question doesn't answer to my question because my question about compatibility of Kotlin extension functions with Java classes.
You're right. In Kotlin 1.0, you can define extension functions on a companion object of a Kotlin class, and such functions can be called using the A.foo() syntax. Support for defining static extension functions on Java classes is a possible feature for future versions of Kotlin, but it's not on the roadmap of Kotlin 1.1 at this time.