Tengo una interfaz con un método predeterminado, y dos clases que implementan esta interfaz. Una de las clases reemplaza el método por defecto, y el otro no.
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"
}
Consigo el acceso al giveHello
método que utiliza la reflexión de esta manera:
val methodOfPolite = Polite::class.java.getDeclaredMethod("giveHello")
val methodOfRude = Rude::class.java.getDeclaredMethod("giveHello")
Hay una cosa extraña aquí. La clase educado no anula el giveHello
método, pero el declaringClass
de este método objeto todavía señala a Polite
.
Entonces, ¿hay alguna manera de comprobar si la clase de hecho no anula el método de interfaz por defecto o no?
Mi caso de uso es como la siguiente (suponiendo que podemos obtener el comportamiento que estoy pidiendo en una propiedad llamada isOverriden
):
if (methodOfPolite.isOverriden) {
// do something
} else {
// do something else
}
Como se describe en KT-4779 , actualmente funciones predeterminadas Kotlin no se implementan utilizando métodos actuales por defecto de Java / JVM. Las vidas de aplicación por defecto en un método estático en lugar, y utilizando todas las clases que la aplicación por defecto simplemente llaman a ese método estático. Esto se hace para asegurar las funciones predeterminadas Kotlin también a trabajar en el objetivo 1.6 JVM que no tiene todavía.
Por lo que su código se compila más o menos equivalente a este de 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" }
}
Esta es la razón por la reflexión de Java piensa que ambas clases tienen prioridad sobre la función, es decir, debido a que realmente hacen.
Es necesario utilizar Kotlin reflexión aquí, en particular declaredMemberFunctions
, y memberFunctions
:
fun overridesGiveHello(cls: KClass<Derp>) =
cls.memberFunctions.first { it.name == "giveHello" } in cls.declaredFunctions
println(overridesGiveHello(Polite::class)) //false
println(overridesGiveHello(Rude::class)) //true