Datenklassen scheinen der Ersatz für die altmodischen POJOs in Java zu sein. Es ist durchaus zu erwarten, dass diese Klassen eine Vererbung ermöglichen, aber ich sehe keine bequeme Möglichkeit, eine Datenklasse zu erweitern. Was ich brauche ist so etwas:
open data class Resource (var id: Long = 0, var location: String = "")
data class Book (var isbn: String) : Resource()
Der obige Code schlägt aufgrund von component1()
Methodenkonflikten fehl . Das Belassen von data
Anmerkungen nur in einer der Klassen erledigt die Arbeit ebenfalls nicht.
Vielleicht gibt es eine andere Redewendung, um Datenklassen zu erweitern?
UPD: Ich kann nur untergeordnete untergeordnete Klassen mit data
Anmerkungen versehen, aber mit Anmerkungen werden nur Eigenschaften behandelt, die im Konstruktor deklariert sind. Das heißt, ich müsste alle Eigenschaften der Eltern deklarieren open
und überschreiben, was hässlich ist:
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()
quelle
componentN()
, die den Wert der N-ten Eigenschaft zurückgeben. Siehe Dokumente zu Multi-DeklarationenAntworten:
Die Wahrheit ist: Datenklassen spielen mit Vererbung nicht so gut. Wir erwägen, die Vererbung von Datenklassen zu verbieten oder stark einzuschränken. Es ist beispielsweise bekannt, dass es keine Möglichkeit gibt, nicht
equals()
abstrakte Klassen in einer Hierarchie korrekt zu implementieren .Alles, was ich anbieten kann: Verwenden Sie keine Vererbung mit Datenklassen.
quelle
Deklarieren Sie Eigenschaften in der Oberklasse außerhalb des Konstruktors als abstrakt und überschreiben Sie sie in der Unterklasse.
quelle
Type Mismatch
Fehlermeldung "Erforderliches T, gefunden: Ressource". Können Sie mir bitte sagen, wie es in Generika verwendet werden kann?Location(long: Double, lat: Double))
in einer anderen?Die obige Lösung unter Verwendung einer abstrakten Klasse generiert tatsächlich eine entsprechende Klasse und lässt die Datenklasse daraus erweitern.
Wenn Sie keine abstrakte Klasse bevorzugen, wie wäre es dann mit einer Schnittstelle ?
Die Schnittstelle in Kotlin kann Eigenschaften haben, wie in diesem Artikel gezeigt .
Ich war gespannt, wie Kotlin das kompiliert. Hier ist äquivalenter Java-Code (generiert mit der Intellij-Funktion [Kotlin-Bytecode]):
Wie Sie sehen, funktioniert es genau wie eine normale Datenklasse!
quelle
@ Željko Trogrlić Antwort ist richtig. Aber wir müssen die gleichen Felder wie in einer abstrakten Klasse wiederholen.
Auch wenn wir abstrakte Unterklassen innerhalb der abstrakten Klasse haben, können wir in einer Datenklasse keine Felder aus diesen abstrakten Unterklassen erweitern. Wir sollten zuerst eine Datenunterklasse erstellen und dann Felder definieren.
quelle
Kotlin Traits können helfen.
Datenklassen
Beispielnutzung
Dieser Ansatz kann auch eine Problemumgehung für Vererbungsprobleme mit @Parcelize sein
quelle
Sie können eine Datenklasse von einer Nicht-Datenklasse erben. Das Erben einer Datenklasse von einer anderen Datenklasse ist nicht zulässig, da vom Compiler generierte Datenklassenmethoden im Falle einer Vererbung nicht konsistent und intuitiv funktionieren können.
quelle
Während die
equals()
korrekte Implementierung in einer Hierarchie in der Tat eine ziemliche Herausforderung darstellt, wäre es dennoch hilfreich, die Vererbung anderer Methoden zu unterstützen, zum Beispiel :toString()
.Um etwas konkreter zu sein, nehmen wir an, wir haben das folgende Konstrukt (offensichtlich funktioniert es nicht, weil
toString()
es nicht vererbt wird, aber wäre es nicht schön, wenn es so wäre?):Unter der Annahme , unseren
User
undLocation
Organisationen ihren entsprechenden Ressourcen - IDs zurückgeben (UserResourceId
undLocationResourceId
jeweils), AufruftoString()
auf jedemResourceId
in einer recht netten kleinen Darstellung führen könnten , die für alle Subtypen im Allgemeinen gilt:/users/4587
,/locations/23
usw. Leider, denn nicht die zu verdrängte geerbte SubtypentoString()
Verfahren aus dem abstrakte BasisResourceId
, Aufruf führttoString()
tatsächlich zu einer weniger hübschen Darstellung :<UserResourceId(id=UserId(value=4587))>
,<LocationResourceId(id=LocationId(value=23))>
Es gibt andere Möglichkeiten, das oben Genannte zu modellieren, aber diese Möglichkeiten zwingen uns entweder dazu, Nicht-Datenklassen zu verwenden (wobei viele Vorteile von Datenklassen fehlen), oder wir kopieren / wiederholen die
toString()
Implementierung in allen unseren Datenklassen (keine Vererbung).quelle
Sie können eine Datenklasse von einer Nicht-Datenklasse erben.
Basisklasse
Kinderklasse
Es funktionierte.
quelle