Классы данных, кажется, заменяют старомодные POJO в Java. Вполне ожидаемо, что эти классы позволят наследовать, но я не вижу удобного способа расширить класс данных. Что мне нужно, это что-то вроде этого:
open data class Resource (var id: Long = 0, var location: String = "")
data class Book (var isbn: String) : Resource()
Приведенный выше код не работает из-за столкновения component1()
методов. Оставить data
аннотацию только в одном из классов тоже не нужно.
Возможно, есть другая идиома для расширения классов данных?
UPD: я мог бы аннотировать только дочерний дочерний класс, но data
аннотация обрабатывает только свойства, объявленные в конструкторе. То есть я должен был бы объявить все родительские свойства open
и переопределить их, что ужасно:
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
Дмитрий
источник
источник
componentN()
которые возвращают значение N-го свойства. Смотрите документы по мульти-декларациямОтветы:
Правда в том, что классы данных не слишком хорошо играют с наследованием. Мы рассматриваем возможность запрета или строгого ограничения наследования классов данных. Например, известно, что нет способа
equals()
правильно реализовать в иерархии неабстрактных классов.Итак, все, что я могу предложить: не использовать наследование с классами данных.
источник
Объявите свойства в суперклассе вне конструктора как абстрактные и переопределите их в подклассе.
источник
Type Mismatch
ошибку: «Требуется T, Найдено: Ресурс». Подскажите, пожалуйста, как его можно использовать в Generics?Location(long: Double, lat: Double))
в другом?Вышеупомянутое решение с использованием абстрактного класса фактически генерирует соответствующий класс, и пусть класс данных расширяется от него.
Если вы не предпочитаете абстрактный класс, как насчет использования интерфейса ?
Интерфейс в Kotlin может иметь свойства, как показано в этой статье .
Мне было любопытно, как Котлин скомпилирует это. Вот эквивалентный Java-код (сгенерированный с помощью функции Intellij [Kotlin bytecode]):
Как видите, он работает точно так же, как обычный класс данных!
источник
@ Желько Трогрлич ответ правильный. Но мы должны повторить те же поля, что и в абстрактном классе.
Также, если у нас есть абстрактные подклассы внутри абстрактного класса, то в классе данных мы не можем расширять поля из этих абстрактных подклассов. Сначала мы должны создать подкласс данных, а затем определить поля.
источник
Черты Kotlin могут помочь.
классы данных
пример использования
Этот подход также может быть решением проблемы наследования с @Parcelize
источник
Вы можете наследовать класс данных от не-класса данных. Наследование класса данных от другого класса данных не допускается, потому что нет способа заставить сгенерированные компилятором методы класса данных работать последовательно и интуитивно в случае наследования.
источник
При реализации
equals()
правильно в иерархии действительно довольно рассол, он все равно будет приятно поддерживать наследуя другие методы, например:toString()
.Чтобы быть немного более конкретным, давайте предположим, что у нас есть следующая конструкция (очевидно, она не работает, потому что
toString()
не наследуется, но было бы неплохо, если бы это было?):Предполагая , что наши
User
иLocation
лица возвращают свои соответствующие идентификаторы ресурсов (UserResourceId
иLocationResourceId
соответственно), позвонивtoString()
по любомуResourceId
могут привести к довольно красивому представлению мало , что , как правило , действует для всех подтипов:/users/4587
,/locations/23
и т.д. К сожалению, из - за не подтипы унаследованы переопределенномtoString()
методы из абстрактный базовыйResourceId
, вызываяtoString()
фактически приводит к менее симпатичной представления:<UserResourceId(id=UserId(value=4587))>
,<LocationResourceId(id=LocationId(value=23))>
Существуют и другие способы моделирования вышеупомянутого, но эти способы либо заставляют нас использовать не-классы данных (упуская многие преимущества классов данных), либо мы заканчиваем копированием / повторением
toString()
реализации во всех наших классах данных. (без наследства).источник
Вы можете наследовать класс данных от не-класса данных.
Базовый класс
детский класс
Это сработало.
источник