J'ai un ensemble de classes de données qui partagent certains champs communs. Idéalement, j'aimerais les déclarer dans un super-type (Message dans cet exemple), et pouvoir écrire des fonctions qui opèrent sur le super-type si elles ont besoin d'accéder à ces champs communs (messageId dans cet exemple).
fun operate(m: Message) {
use(m.messageId)
}
J'ai essayé d'y parvenir en étendant mes classes de données à partir d'une classe scellée.
Les classes de données peuvent étendre les classes scellées, mais je ne suis pas sûr qu'elles puissent accepter les arguments requis par la classe scellée "supertype".
-
L'extension d'une classe ordinaire à partir d'une classe scellée se compile très bien.
sealed class Message(val messageId: String) class Track(val event: String, messageId: String): Message(messageId)
-
Cependant, le changer en une classe de données ne compile pas ("Le constructeur primaire de la classe de données ne doit avoir que des paramètres de propriété (val/var)").
sealed class Message(val messageId: String) data class Track(val event: String, messageId: String): Message(messageId)
-
Déclarer le paramètre en tant que propriété ne compile pas non plus ("'messageId' hides member of supertype 'Message' and needs 'override' modifier'").
sealed class Message(val messageId: String) data class Track(val event: String, val messageId: String): Message(messageId)
-
Ouvrir la propriété supertype et la surcharger dans chacune des classes de base compile bien :
sealed class Message(open val messageId: String) data class Track(val event: String, override val messageId: String): Message(messageId)
Idéalement, j'aimerais quelque chose de proche de l'option 2 - cela me permet de combiner le meilleur des deux mondes.
Sinon, il me semble que mes options sont soit d'élaborer à la main mes propres fonctionnalités de classe de données (copie, code de hachage, égaux, etc.) avec l'option 1, soit de vivre avec un compromis en ouvrant les propriétés des super-types avec l'option 4.