简体   繁体   中英

Kotlin to Java interoperability in hierarchial interfaces

I have two modules defines like this:

interface Module {
    val parameter: JSONObject
}

abstract class FirstModule: Module {
    abstract val message: Message
}
....
// many more Modules

I created a base listener interface for Module and another for FirstModule :

fun interface ModuleListener {
    fun ready(module: Module)
}

fun interface FirstModuleListener: ModuleListener {
    fun ready(module : FirstModule)

    override fun ready(module: Module) {
        ready(module as FirstModule)
    }
}

assuming there is a function named firstModule() like this:

fun firstModule(listener: FirstModuleListener)

In KOTLIN when I call firstModule() things work as expected (to let user only override ready() with FirstModule as parameter:

firstModule ( object: FirstModuleListener {
       override fun ready(module: FirstModule) {
           Log.v(TAG, "module: $module)
       }
    }
}

but the same is behaving differently in JAVA . It is expecting user to override both the interface methods even when one of them is already overridden and has some content in child interface.

firstModule(new FirstModuleListener() {
   @Override public void ready(Module module) { }

   @Override public void ready(FirstModule module) {}
}

How can I skip the first overridden method call in Java. Is it causing due to the method definition support in Kotlin and not in Java?

Essentially: When kotlin implements FirstModuleListener interface, it still implements two ready() .

In FirstModuleListener , fun ready(module: FirstModule) is an abstract method, and

override fun ready(module: Module) {
        ready(module as FirstModule)
    }

It is a concrete realization method.

The interface in kotlin can define specific methods, and the kotlin compiler behind it is converted into the corresponding static method in Java. Your FirstModuleListener defines both abstract and non-abstract methods.

Kotlin will generate a DefaultImpls static inner class to implement the ready(module: Module) method of FirstModuleListener at compile time.

public interface FirstModuleListener extends ModuleListener {
   void ready(@NotNull FirstModule var1);

   void ready(@NotNull Module var1);

   @Metadata(
      mv = {1, 5, 1},
      k = 3
   )
   public static final class DefaultImpls {
      public static void ready(@NotNull FirstModuleListener $this, @NotNull Module module) {
         Intrinsics.checkNotNullParameter(module, "module");
         $this.ready((FirstModule)module);
      }
   }
}

When implementing FirstModuleListener , a ready() essentially calls ready() of DefaultImpls .

 firstModule((FirstModuleListener)(new FirstModuleListener() {
         public void ready(@NotNull FirstModule module) {
            Intrinsics.checkNotNullParameter(module, "module");
         }

         public void ready(@NotNull Module module) {
            Intrinsics.checkNotNullParameter(module, "module");
            FirstModuleListener.DefaultImpls.ready(this, module);
         }
      }));

This is no different from Java.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM