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)