¿Cómo usar la inheritance simple para la class de datos?

En Java,

abstract class NumericValue{ private String a; private String b; public String getA() { return a; } public void setA(String a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NumericValue that = (NumericValue) o; if (a != null ? !a.equals(that.a) : that.a != null) return false; return b != null ? b.equals(that.b) : that.b == null; } @Override public int hashCode() { int result = a != null ? a.hashCode() : 0; result = 31 * result + (b != null ? b.hashCode() : 0); return result; } } class Abc extends NumericValue{ public static void main(String[] args) { Abc abc = new Abc(); abc.getA(); } } 

En Kotlin, esto se networkinguce a:

Enfoque 1:

 sealed class NumericValueA{ abstract var a: String abstract var b: String } data class AbcA( override var a:String, override var b:String ):NumericValueA() 

Enfoque 2:

 open class NumericValueB( open var a:String, open var b:String ) data class AbcB( override var a:String, override var b:String ):NumericValueB(a,b) 

Ambos enfoques tienden a la duplicación masiva cuando tienes classs de datos que simplemente henetworkingan attributes, ya que tienes que anotar todo lo que has especificado nuevamente, esto simplemente no se escala y de alguna manera se siente mal.

¿Es este el estado del arte o es realmente la mejor manera de traducir el antiguo código java a kotlin?

IntelliJ Idea traduce su código Java en lo siguiente que parece razonable y networkingucido en la placa de la caldera. Entonces, yo respondería: "No, su premisa no caracteriza con precisión si Kotlin es o no es lo último en tecnología".

 internal abstract class NumericValue { var a: String? = null var b: String? = null override fun equals(o: Any?): Boolean { if (this === o) return true if (o == null || javaClass != o.javaClass) return false val that = o as NumericValue? if (if (a != null) a != that!!.a else that!!.a != null) return false return if (b != null) b == that.b else that.b == null } override fun hashCode(): Int { var result = if (a != null) a!!.hashCode() else 0 result = 31 * result + if (b != null) b!!.hashCode() else 0 return result } } internal class Abc : NumericValue() { companion object { @JvmStatic fun main(args: Array<String>) { val abc = Abc() abc.a } } } 

Pero su pregunta se dirige específicamente a las classs de "datos". Las classs de datos son un buen componente del lenguaje que nos da "deconstrucción" y algunos methods útiles para la deconstrucción generados automáticamente (como el componentN ). Entonces, usando el código de arriba (y agregando open a la class y las declaraciones de b ), aquí hay una implementación ligeramente diferente de su class derivada de ejemplo.

 internal data class AbcB (override var a: String?, override var b: String?) : NumericValue() { companion object { @JvmStatic fun main(args: Array<String>) { val abc = AbcB("a","b") println("b = " + abc.component2()) val n: NumericValue = abc println("a = " + na) } } } 

Lo cual parece razonable, en ese sentido, su ejemplo inicial no es una class de datos y su aparente deseo es hacer uso de la class de datos de Kotlin. Le da una característica deseable (si la necesita), a costa de un poco más de código de verbage.

La class derivada es el mismo código si declara la base como sealed y a y b como abstract .

Entonces, en el caso de classs de datos, hay una duplicación de cualquier parte de la class base que quiera exponer como "datos" en la class derivada (ya está expuesta, pero no como miembros especiales de "class de datos", como se muestra en el ejemplo a continuación). Pero esto es análogo a las anulaciones en otros contexts. Solo por pensamiento, considere ahora la siguiente class derivada.

 internal data class AbcCD (var c: String?, var d: String?) : NumericValue() { companion object { @JvmStatic fun x() { val abc = AbcCD("c","d") abc.b = "B" abc.a = "A" println("d = " + abc.component2()) abc.a } } } 

Obtiene todos los miembros de la class base y los nuevos miembros de datos de la class derivada. Pero si desea anular los beneficios, nuevamente cuesta algunos verbos sintácticos (para classs de datos derivados y classs regulares).

Un último punto. Las classs de datos todavía tienen otras rarezas asociadas con la inheritance y anulaciones que aún deben resolverse. toString , hashCode y equals obtienen sus propias implementaciones especiales y la documentation dice …

Si hay implementaciones explícitas de equals (), hashCode () o toString () en el cuerpo de la class de datos o implementaciones finales en una superclass, estas funciones no se generan y se usan las implementaciones existentes;

… que me resulta confuso de leer (lo que me lleva a experimentar en lugar de confiar en los documentos). Y hay otras preguntas de SO relacionadas con las luchas sobre classs toString y Data (por ejemplo: este OP intenta crear un DTO ).

Por lo tanto , creo que este es el estado de la técnica y no es tan malo (IMO). Y sí, si quieres las características de las classs de datos, puedes traducirlo más o less como lo has hecho.

  • Error de inyección de Android Kotlin dagger 2 ViewModel
  • intelliJ IDEA generado file ant no genera files
  • No se puede comprimir Rxjava Observables
  • Cómo ejecutar algún código cuando Gradle está construyendo las testings
  • Función de extensión Kotlin: reference no resuelta
  • DBFlow: datos de consulta de la columna especificada
  • No se proporcionan suficientes datos a HAL, position esperada
  • Kotlin construye causando JVM a la falla de segmentación
  • ¿Cómo get una instancia delegada en Kotlin?
  • Realm Turn Transaction en observable
  • Ejecute testings junit escritas en Kotlin con la anotación @category