How to check if a class has overriden a default method from an interface using Reflection in Kotlin or Java?

har*_*min 4 java reflection kotlin

I have an interface with a default method, and two classes which implement this interface. One of the classes overrides the default method, and the other does not.

interface MyType {
  fun giveHello(): String = "Hello!"
}

class Polite: MyType {
  // Does not override giveHello()
}

class Rude: MyType {
  override fun giveHello(): String = "I don't like you"
}
Run Code Online (Sandbox Code Playgroud)

我可以giveHello使用反射来访问该方法,如下所示:

val methodOfPolite = Polite::class.java.getDeclaredMethod("giveHello")
val methodOfRude = Rude::class.java.getDeclaredMethod("giveHello")
Run Code Online (Sandbox Code Playgroud)

这里有一件事很奇怪。有礼貌的类不会覆盖giveHello方法,但declaringClass此方法对象的仍指向Polite

因此,有没有一种方法可以检查该类是否确实覆盖了默认接口方法?

我的用例看起来像这样(假设我们可以在名为的属性中获得我要的行为isOverriden):

if (methodOfPolite.isOverriden) {
  // do something
} else {
  // do something else
}
Run Code Online (Sandbox Code Playgroud)

Tod*_*ell 6

KT-4779中所述,当前Kotlin默认功能尚未使用实际的Java / JVM默认方法实现。默认实现使用静态方法代替,并且使用该默认实现的所有类都将调用该静态方法。这样做是为了确保Kotlin默认功能也可以在尚不存在的1.6 JVM目标上运行。

因此,您的代码大致可以编译为以下Java等效代码:

public interface MyType {
  public String giveHello();

  public static class MyTypeImpls {
     public static String giveHello() { return "Hello!" }
  }
}

public final class Polite implements MyType {
  //does not override
  public String giveHello() { return MyType.MyTypeImpls.giveHello() }
}

public final class Rude implements MyType {
  //does override
  override fun giveHello() { return "I don't like you" }
}
Run Code Online (Sandbox Code Playgroud)

这就是Java反射认为两个类都覆盖该函数的原因,即因为它们确实起作用。

您需要在此处使用Kotlin反射,尤其是declaredMemberFunctionsmemberFunctions

fun overridesGiveHello(cls: KClass<Derp>) =
        cls.memberFunctions.first { it.name == "giveHello" } in cls.declaredFunctions

println(overridesGiveHello(Polite::class)) //false
println(overridesGiveHello(Rude::class))  //true
Run Code Online (Sandbox Code Playgroud)