descargar - kotlin vs scala
¿Cómo superar el error de “misma firma JVM” al implementar una interfaz Java? (7)
¡Podemos hacer esto!
package com.example.mykotlin
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv.text = "Hello MyKotlin"
tv.textSize = 20.0f
}
}
Con el siguiente código, recibo el siguiente error en IntelliJ IDEA 13.1.6 y Kotlin plugin 0.11.91.AndroidStudio.3:
Platform declaration clash: The following declarations have the same JVM signature (getName()Ljava/lang/String;):
• public open fun getName(): kotlin.String?
• internal final fun <get-name>(): kotlin.String?
Clase de Java, JavaInterface.java
:
public interface JavaInterface {
public String getName();
}
Clase de Kotlin, KotlinClass.kt
public class KotlinClass(val name: String?) : JavaInterface
He intentado anular el método ''getter'' agregando override fun getName(): String? = name
override fun getName(): String? = name
, pero que produce el mismo error.
Puedo ver una solución al hacer esto en su lugar:
public class KotlinClass(val namePrivate: String?) : JavaInterface {
override fun getName(): String? = namePrivate
}
Pero en mi caso del mundo real tengo una serie de propiedades para implementar y también necesito configuradores. Hacer esto para cada propiedad no parece muy Kotlin-ish. ¿Qué me estoy perdiendo?
Hacer que la variable sea private
resuelve el problema.
public class KotlinClass(private val name: String?) : JavaInterface
Hemos encontrado que para usar los mismos nombres sin chocar, ctor args debe ser privado Y aún debe anular los métodos de interfaz. No necesita campos de respaldo adicionales . Además, la asignación del cuerpo de la expresión no se repetirá, por lo que puede usar esa sintaxis de forma segura.
Interfaz de Java
interface IUser {
String getUserScope();
String getUserId();
}
Clase de kotlin
class SampleUser(private val userScope: String, private val userId: String) : IUser {
override fun getUserId() = userId
override fun getUserScope() = userScope
}
Otra solución es declarar las propiedades en una clase abstracta de Kotlin, luego escribir una clase java pequeña que amplíe KotlinClass e implemente JavaInterface.
// JavaInterface.java
public interface JavaInterface {
int getFoo();
void setFoo(int value);
}
// KotlinClass.kt
abstract class KotlinClass(open var foo : Int = 0) {
}
// JavaAdapter.java
class JavaAdapter extends KotlinClass implements JavaInterface {
// all code in KotlinClass, but can''t implement JavaInterface there
// because kotlin properties cannot override java methods.
}
Podría usar @JvmField para indicar al compilador que no genere getter / setter, y puede implementar sus setters y getters. Con esto, su código funciona bien en Java (como atributo getter / setter) y Kotlin como propiedad
Ejemplo: JAVA :
public interface Identifiable<ID extends Serializable>
{
ID getId();
}
KOTLIN :
class IdentifiableImpl(@JvmField var id: String) :Identifiable<String>
{
override fun getId(): String
{
TODO("not implemented")
}
}
Si tiene control directo sobre la interfaz, el mejor enfoque es escribir la interfaz en Kotlin. A continuación, puede escribir su clase
public class KotlinClass(override val name: String?) : KotlinInterface
y sigue haciéndolo referencia desde cualquier código Java usando la misma interfaz que antes. Esto se ve mucho mejor que establecer todas las propiedades en privado y anular la función de obtención. Obviamente, si no puede migrar la interfaz a Java porque no la posee, entonces esa parece ser la única solución.
public interface JavaInterface {
public String getName();
}
public class KotlinClass(val namePrivate: String?) : JavaInterface {
private var name = namePrivate
override fun getName(): String? {
return name
}
}