Extending Groovy class from Kotlin

When I try to extend Groovy class in Kotlin, Kotlin compiler complains about missing methods from GroovyObject (getMetaClass, etc). For example:

object : MyGroovyClass() {
	override fun fooo() {
		// ...
	}
}

results in error Object must be declared abstract or implement abstract base class member public abstract fun setProperty(p0: String!, p1: Any!): Unit defined in MyGroovyClass

Groovy classes can be extended from Java and Scala. I was wondering what is special about Kotlin? Does it ignore synthetic methods or I missed something?

3 Likes

I had tried extend NpmTask and got same error.

I found in a hard way that Groovy is not very backwards compatible with java and therefore kotlin. You can surely call both java and kotlin classes from Groovy (in case of kotlin it is a bit disappointing since Groovy and Kotlin have many similar features, but they are not interoperable), but you can’t easily call Groovy from Java and Kotlin. In theory, you can, but Groovy dynamic features always get in a way.
First recommendation: Do not try to do it. Implement all your logic in Kotlin/Java and Groovy only as a fine user interface layer.
Second recommendation. If you definitely need it, use a groovy @CompileStatic.

In your case, you can try to create a groovy wrapper class extending NpmTask and make it call some Kotlin code (calls from Groovy to Kotlin work just fine).

2 Likes

The short answer is, yes, Kotlin compiler does ignore synthetic methods in Groovy class bytecode. And @CompileStatic doesn’t help in this situation.

The workaround I’m current using is creating a bridge KotlinExtendsGroovyWorkaround.java file then extends it in Kotlin.

public class KotlinExtendsGroovyWorkaround extends NpmTask {
    @Override
    public Object invokeMethod(String s, Object o) {
        return super.invokeMethod(s, o);
    }

    @Override
    public Object getProperty(String s) {
        return super.getProperty(s);
    }

    @Override
    public void setProperty(String s, Object o) {
        super.setProperty(s, o);
    }

    @Override
    public MetaClass getMetaClass() {
        return super.getMetaClass();
    }

    @Override
    public void setMetaClass(MetaClass metaClass) {
        super.setMetaClass(metaClass);
    }
}
2 Likes

@blindpirate I know it was quite a while ago, but maybe you still know the answer :slight_smile:

I tried your way but I get a compile error:
image

So is there any magic in your Groovy class? :slight_smile:

2 Likes