A note for people using Mixins which implement interfaces which have default implementations of methods which are written in Kotlin.
Lets say you have an interface in Kotlin:
interface MyKotlinterface {
fun doMyThing() {
x.y.z.doThing(this)
}
}
and a mixin:
@Mixin(PlayerEntity.class)
abstract class MyMixin implements MyKotlinterface {}
you might think that you can then do (player as MyKotlinterface).doMyThing(). However, you will get an AbstractMethodError. Why? because Kotlin doesn't compile your interface how you'd expect it to.
You'd think that it would compile like:
public interface MyKotlinterface {
public default void doMyThing() {
x.y.z.doThing(this)
}
}
but that would only work on JVMs at or above version 8, when default implementations for methods in interfaces were added - so Kotlin compiles it like this instead, which works on all JVMs:
public interface TestInterface {
/* All calls to the default impl of this method
* are rewritten by the kotlin compiler to use
* the static method
*/
public void doMyThing();
public static final class DefaultImpls {
public static void doMyThing(TestInterface obj) {
x.y.z.doThing(obj)
}
}
}
The side-effect of this is that when you add your interface to a class with that mixin, it bypasses the kotlin compiler's rewriting - and so, attempts to access the default impl of the method on the player will crash with an AbstractMethodError. There are different fixes for this, depending on which Kotlin version you're using:
- For Kotlin <1.2, you'll have to just write your implementations in your mixin class.
- For Kotlin 1.2<=version<1.4, annotate your method with
@JvmDefault, and put this in your build.gradle:
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += '-Xjvm-default'
}
}
- For Kotlin >=1.4, just put this in your build.gradle:
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += '-Xjvm-default=all'
}
}
and your default methods will be compiled as they should be!
with thanks to this blog post and this decompiler/bytecode viewer
Top comments (0)