Las clases de datos parecen ser el reemplazo de los POJO anticuados en Java. Es bastante esperable que estas clases permitan la herencia, pero no veo una manera conveniente de extender una clase de datos. Lo que necesito es algo como esto:
open data class Resource (var id: Long = 0, var location: String = "")
data class Book (var isbn: String) : Resource()
El código anterior falla debido al choque de component1()
métodos. Dejandodata
anotaciones en solo una de las clases tampoco hace el trabajo.
¿Quizás hay otro idioma para extender las clases de datos?
UPD: podría anotar solo la clase secundaria hijo, pero la data
anotación solo maneja las propiedades declaradas en el constructor. Es decir, tendría que declarar todas las propiedades de los padres open
y anularlas, lo cual es feo:
open class Resource (open var id: Long = 0, open var location: String = "")
data class Book (
override var id: Long = 0,
override var location: String = "",
var isbn: String
) : Resource()
inheritance
kotlin
abstract
data-class
Dmitry
fuente
fuente
componentN()
que devuelven el valor de la propiedad N-ésima. Ver documentos sobre Declaraciones MúltiplesRespuestas:
La verdad es que las clases de datos no juegan demasiado bien con la herencia. Estamos considerando prohibir o restringir severamente la herencia de las clases de datos. Por ejemplo, se sabe que no hay forma de implementar
equals()
correctamente en una jerarquía en clases no abstractas.Entonces, todo lo que puedo ofrecer: no use la herencia con clases de datos.
fuente
Declare las propiedades en la superclase fuera del constructor como abstractas y anúlelas en la subclase.
fuente
Type Mismatch
error: "T obligatorio, encontrado: Recurso". ¿Me puede decir cómo se puede usar en genéricos?Location(long: Double, lat: Double))
en otra?La solución anterior que usa la clase abstracta en realidad genera la clase correspondiente y deja que la clase de datos se extienda desde ella.
Si no prefiere la clase abstracta, ¿qué tal usar una interfaz ?
La interfaz en Kotlin puede tener propiedades como se muestra en este artículo .
Tenía curiosidad por cómo Kotlin compila esto. Aquí hay un código Java equivalente (generado usando la función Intellij [Kotlin bytecode]):
Como puede ver, ¡funciona exactamente como una clase de datos normal!
fuente
La respuesta de @ Željko Trogrlić es correcta. Pero tenemos que repetir los mismos campos que en una clase abstracta.
Además, si tenemos subclases abstractas dentro de la clase abstracta, entonces en una clase de datos no podemos extender los campos de estas subclases abstractas. Primero debemos crear una subclase de datos y luego definir campos.
fuente
Los rasgos de Kotlin pueden ayudar.
clases de datos
uso de muestra
Este enfoque también puede ser una solución para problemas de herencia con @Parcelize
fuente
Puede heredar una clase de datos de una clase que no sea de datos. No se permite heredar una clase de datos de otra clase de datos porque no hay forma de hacer que los métodos de clase de datos generados por el compilador funcionen de manera coherente e intuitiva en caso de herencia.
fuente
Si bien la implementación
equals()
correcta en una jerarquía es bastante difícil, aún sería bueno admitir heredar otros métodos, por ejemplo:toString()
.Para ser un poco más concreto, supongamos que tenemos la siguiente construcción (obviamente, no funciona porque
toString()
no se hereda, pero ¿no sería bueno si lo hiciera?):Asumiendo nuestra
User
yLocation
entidades devolver su ID de los recursos apropiados (UserResourceId
yLocationResourceId
respectivamente), llamartoString()
en cualquierResourceId
podría resultar en una representación muy poco agradable que es válido en general para todos los subtipos:/users/4587
,/locations/23
, etc. Por desgracia, porque no de los subtipos heredó a sobrescritotoString()
el método de la base abstractaResourceId
, llamandotoString()
en realidad se traduce en una representación menos bonita:<UserResourceId(id=UserId(value=4587))>
,<LocationResourceId(id=LocationId(value=23))>
Hay otras formas de modelar lo anterior, pero esas formas nos obligan a usar clases que no son de datos (perdiendo muchos de los beneficios de las clases de datos), o terminamos copiando / repitiendo la
toString()
implementación en todas nuestras clases de datos (sin herencia)fuente
Puede heredar una clase de datos de una clase que no sea de datos.
Clase base
clase infantil
Funcionó.
fuente