Estoy escribiendo una clase que implementa una interfaz que expone un método setSelected . Esta clase tendrá una propiedad selected :
private class Foo : IFoo { var selected = false override fun setSelected(isActive: Boolean) { selected = isActive } } Sin embargo, el compilador se queja, ya que Kotlin genera un setter para selected , de que los dos métodos chocan:
Error:(14, 9) Kotlin: [com.bar.jvmTest] Platform declaration clash: The following declarations have the same JVM signature (setSelected(Z)V): fun <set-selected>(<set-?>: Boolean): Unit defined in foo.bar.baz.Foo fun setSelected(isActive: Boolean): Unit defined in foo.bar.baz.Foo Error:(24, 9) Kotlin: [com.bar.jvmTest] Platform declaration clash: The following declarations have the same JVM signature (setSelected(Z)V): fun <set-selected>(<set-?>: Boolean): Unit defined in foo.bar.baz.Foo fun setSelected(isActive: Boolean): Unit defined in foo.bar.baz.Foooverride y, por lo tanto, mi clase no implementa completamente la interfaz: Error:(11, 13) Kotlin: [com.bar.jvmTest] Class 'Foo' is not abstract and does not implement abstract member public abstract fun setSelected(isActive: Boolean): Unit defined in bar.bazselected a, por ejemplo, dataSelected para que el setter generado no entre en conflicto con el método, pero debería haber una manera de mantener este nombre de propiedad simple e implementar la interfaz como se esperaba.override ?Puede crear una propiedad sin un campo de respaldo y luego anular su función abstracta de esta manera:
class Foo : IFoo { private var hiddenSelected = false val selected get() = hiddenSelected override fun setSelected(isActive: Boolean) { hiddenSelected = isActive } }Actualizar:
Después de dormir, creo que esta solución no es tan buena por 2 razones:
hiddenSelected ) que no es necesario= operador)Creo que la mejor solución sería esta:
class Foo : IFoo { @set:JvmName("setSelected0") var selected: Boolean = false set(value) { setSelected(value) } override fun setSelected(isActive: Boolean) { // Possibly some other stuff println("Now i'm using my own setter!") selected = isActive } } Usando la anotación @JvmName , puede decirle al compilador cómo nombrar esa función específica. Kotlin crea automáticamente un getter y setter para cada propiedad, por lo que debe usar el modificador set: para anotar el setter de esa propiedad y no la propiedad en sí.
También es muy importante que implemente un setter personalizado para esa propiedad para que pueda escribir esto de manera segura :
Foo().selected = true // This also prints "Now i'm using my own setter!"en lugar de esto:
Foo().setSelected(true) Es posible que su colocador pueda hacer otras cosas (como imprimir ese registro), lo que puede tener efectos secundarios, por lo que debe asegurarse de llamar al colocador correcto. A veces, esto puede ser un poco complicado, ya que Kotlin siempre crea un setter para cada variable mutable ( var ).
Puede usar @JvmName para cambiar el nombre del setter generado :
private class Foo : IFoo { @set:JvmName("setSelected0") var selected = false override fun setSelected(isActive: Boolean) { selected = isActive } }El uso de Kotlin sigue siendo el mismo.