Wydaje się, że klasy danych zastępują staromodne POJO w Javie. Można się spodziewać, że te klasy pozwoliłyby na dziedziczenie, ale nie widzę wygodnego sposobu na rozszerzenie klasy danych. Potrzebuję czegoś takiego:
open data class Resource (var id: Long = 0, var location: String = "")
data class Book (var isbn: String) : Resource()
Powyższy kod nie działa z powodu kolizji component1()
metod. Pozostawienie data
adnotacji tylko na jednej z klas też nie działa.
Być może istnieje inny idiom do rozszerzania klas danych?
UPD: Mogę data
dodawać adnotacje tylko do klasy potomnej , ale adnotacja obsługuje tylko właściwości zadeklarowane w konstruktorze. Oznacza to, że musiałbym zadeklarować wszystkie właściwości rodzica open
i zastąpić je, co jest brzydkie:
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
źródło
źródło
componentN()
które zwracają wartość N-tej właściwości. Zobacz dokumentację dotyczącą wielu deklaracjiOdpowiedzi:
Prawda jest taka: klasy danych nie współpracują zbyt dobrze z dziedziczeniem. Rozważamy zakaz lub surowe ograniczenie dziedziczenia klas danych. Na przykład wiadomo, że nie ma sposobu, aby
equals()
poprawnie zaimplementować w hierarchii klas nieabstrakcyjnych.A więc wszystko, co mogę zaoferować: nie używaj dziedziczenia z klasami danych.
źródło
Zadeklaruj właściwości w superklasie poza konstruktorem jako abstrakcyjne i zastąp je w podklasie.
źródło
Type Mismatch
błąd: „Wymagane T, znaleziono: zasób”. Czy możesz mi powiedzieć, jak można go używać w generycznych?Location(long: Double, lat: Double))
w innej?Powyższe rozwiązanie wykorzystujące klasę abstrakcyjną faktycznie generuje odpowiednią klasę i pozwala klasie danych na jej rozszerzenie.
Jeśli nie wolisz klasy abstrakcyjnej, co powiesz na użycie interfejsu ?
Interfejs w Kotlin może mieć właściwości, jak pokazano w tym artykule .
Byłem ciekawy, jak Kotlin to kompiluje. Oto równoważny kod Java (wygenerowany przy użyciu funkcji Intellij [kod bajtowy Kotlin]):
Jak widać, działa dokładnie tak, jak zwykła klasa danych!
źródło
@ Željko Trogrlić odpowiedź jest prawidłowa. Ale musimy powtórzyć te same pola, co w klasie abstrakcyjnej.
Również jeśli mamy abstrakcyjne podklasy wewnątrz klasy abstrakcyjnej, to w klasie danych nie możemy rozszerzać pól z tych abstrakcyjnych podklas. Najpierw należy utworzyć podklasę danych, a następnie zdefiniować pola.
źródło
Kotlin Traits może pomóc.
klasy danych
przykładowe użycie
To podejście może być również obejściem problemów z dziedziczeniem z @Parcelize
źródło
Możesz dziedziczyć klasę danych z klasy niebędącej danymi. Dziedziczenie klasy danych z innej klasy danych jest niedozwolone, ponieważ nie ma sposobu, aby metody klas danych generowanych przez kompilator działały spójnie i intuicyjnie w przypadku dziedziczenia.
źródło
O ile
equals()
poprawne implementowanie w hierarchii jest rzeczywiście niezłe, dobrze byłoby wspierać dziedziczenie innych metod, na przykład:toString()
.Aby być bardziej konkretnym, załóżmy, że mamy następującą konstrukcję (oczywiście nie działa, ponieważ
toString()
nie jest dziedziczona, ale czy nie byłoby miło, gdyby tak było?):Zakładając, że nasze
User
iLocation
podmioty wrócić do swoich odpowiednich identyfikatorów zasobów (UserResourceId
iLocationResourceId
odpowiednio), dzwoniąctoString()
na dowolnyResourceId
może spowodować dość ładnym małym reprezentacji, która jest ogólnie ważne dla wszystkich podtypów:/users/4587
,/locations/23
, itd. Niestety, z powodu non podtypów dziedziczona zastąpionejtoString()
metodzie z abstrakt bazaResourceId
, nazywająctoString()
rzeczywiście skutkuje mniej ładna reprezentacji:<UserResourceId(id=UserId(value=4587))>
,<LocationResourceId(id=LocationId(value=23))>
Istnieją inne sposoby modelowania powyższego, ale te sposoby albo zmuszają nas do korzystania z klas innych niż dane (tracą wiele zalet klas danych) lub w końcu kopiujemy / powtarzamy
toString()
implementację we wszystkich naszych klasach danych (bez dziedziczenia).źródło
Możesz dziedziczyć klasę danych z klasy niebędącej danymi.
Klasa podstawowa
klasa podrzędna
Zadziałało.
źródło