Les classes de données semblent remplacer les POJO à l'ancienne en Java. Il est tout à fait prévisible que ces classes permettent l'héritage, mais je ne vois aucun moyen pratique d'étendre une classe de données. Ce dont j'ai besoin est quelque chose comme ça:
open data class Resource (var id: Long = 0, var location: String = "")
data class Book (var isbn: String) : Resource()
Le code ci-dessus échoue en raison d'un conflit de component1()
méthodes. Laisser une data
annotation dans une seule des classes ne fait pas non plus le travail.
Peut-être existe-t-il un autre langage pour étendre les classes de données?
UPD: Je pourrais annoter uniquement la classe enfant enfant, mais l' data
annotation ne gère que les propriétés déclarées dans le constructeur. Autrement dit, je devrais déclarer toutes les propriétés des parents open
et les remplacer, ce qui est moche:
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
la source
la source
componentN()
qui retournent la valeur de la propriété N-ième. Voir la documentation sur les multi-déclarationsRéponses:
La vérité est que les classes de données ne jouent pas très bien avec l'héritage. Nous envisageons d'interdire ou de restreindre sévèrement l'héritage des classes de données. Par exemple, on sait qu'il n'y a aucun moyen d'implémenter
equals()
correctement dans une hiérarchie sur des classes non abstraites.Donc, tout ce que je peux offrir: n'utilisez pas l'héritage avec des classes de données.
la source
Déclarez les propriétés de la super-classe en dehors du constructeur comme abstraites et remplacez-les dans la sous-classe.
la source
Type Mismatch
erreur: "T requis, trouvé: ressource". Pouvez-vous s'il vous plaît me dire comment peut-il être utilisé dans les génériques?Location(long: Double, lat: Double))
dans une autre?La solution ci-dessus utilisant une classe abstraite génère en fait la classe correspondante et laisse la classe de données en étendre.
Si vous ne préférez pas la classe abstraite, que diriez-vous d'utiliser une interface ?
L'interface dans Kotlin peut avoir des propriétés comme indiqué dans cet article .
J'étais curieux de savoir comment Kotlin compilait cela. Voici le code Java équivalent (généré à l'aide de la fonctionnalité Intellij [Kotlin bytecode]):
Comme vous pouvez le voir, cela fonctionne exactement comme une classe de données normale!
la source
@ La réponse de Željko Trogrlić est correcte. Mais nous devons répéter les mêmes champs que dans une classe abstraite.
De même, si nous avons des sous-classes abstraites à l'intérieur de la classe abstraite, alors dans une classe de données, nous ne pouvons pas étendre les champs de ces sous-classes abstraites. Nous devons d'abord créer une sous - classe de données , puis définir des champs.
la source
Kotlin Traits peut vous aider.
classes de données
utilisation de l'échantillon
Cette approche peut également être une solution de contournement pour les problèmes d'héritage avec @Parcelize
la source
Vous pouvez hériter d'une classe de données d'une classe sans données. L'héritage d'une classe de données d'une autre classe de données n'est pas autorisé car il n'existe aucun moyen de faire en sorte que les méthodes de classe de données générées par le compilateur fonctionnent de manière cohérente et intuitive en cas d'héritage.
la source
Bien que la mise en œuvre
equals()
correctement dans une hiérarchie est en effet tout à fait un cornichon, il serait toujours agréable de soutenir héritant d' autres méthodes, par exemple:toString()
.Pour être un peu plus concret, supposons que nous ayons la construction suivante (évidemment, cela ne fonctionne pas car elle
toString()
n'est pas héritée, mais ne serait-ce pas bien si c'était le cas?):En supposant que nos
User
etLocation
entités renvoient leurs ID de ressources appropriées (UserResourceId
etLocationResourceId
respectivement), appelanttoString()
à toutResourceId
pourrait entraîner une très jolie petite représentation qui est généralement valable pour tous les sous - types:/users/4587
,/locations/23
, etc. Malheureusement, à cause non des sous - types hérité de redéfinietoString()
méthode de la base abstraiteResourceId
, appelanttoString()
fait des résultats dans une représentation moins jolie:<UserResourceId(id=UserId(value=4587))>
,<LocationResourceId(id=LocationId(value=23))>
Il existe d'autres façons de modéliser ce qui précède, mais ces méthodes nous obligent soit à utiliser des classes sans données (manquant de nombreux avantages des classes de données), soit nous finissons par copier / répéter l'
toString()
implémentation dans toutes nos classes de données (pas d'héritage).la source
Vous pouvez hériter d'une classe de données d'une classe sans données.
Classe de base
classe enfant
Ça a marché.
la source