Расширить класс данных в Котлине


классы данных, похоже, являются заменой старомодным POJOs в 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()
4 74

4 ответа:

правда в том, что классы данных не слишком хорошо играют с наследованием. Мы рассматриваем возможность запрета или строгого ограничения наследования классов данных. Например, известно, что нет способа реализовать equals() правильно в иерархии на неабстрактных классах.

Итак, все, что я могу предложить: не используйте наследование с классами данных.

объявить свойства в суперклассе вне конструктора как абстрактные и переопределить их в подклассе.

abstract class Resource {
    abstract var id: Long
    abstract var location: String
}

data class Book (
    override var id: Long = 0,
    override var location: String = "",
    var isbn: String
) : Resource()

выше решение с использованием абстрактного класса фактически генерирует соответствующий класс и пусть класс данных простирается от него.

Если вы не предпочитаете абстрактный класс, как об использовании интерфейс?

интерфейс в Котлине может иметь свойства как показано в этой в этой статье..

interface History {
    val date: LocalDateTime
    val name: String
    val value: Int
}

data class FixedHistory(override val date: LocalDateTime,
                        override val name: String,
                        override val value: Int,
                        val fixedEvent: String) : History

мне было любопытно, как Котлин скомпилировать это. Вот эквивалентный код Java (генерируется с использованием байт-кода Intellij [Kotlin] особенность):

public interface History {
   @NotNull
   LocalDateTime getDate();

   @NotNull
   String getName();

   int getValue();
}

public final class FixedHistory implements History {
   @NotNull
   private final LocalDateTime date;
   @NotNull
   private final String name;
   private int value;
   @NotNull
   private final String fixedEvent;

   // Boring getters/setters as usual..
   // copy(), toString(), equals(), hashCode(), ...
}

Как вы можете видеть, это работает точно так же, как обычный класс данных!

вы можете наследовать класс данных от класса без данных. Наследование класса данных от другого класса данных не допускается, поскольку нет способа заставить методы класса данных, созданные компилятором, работать последовательно и интуитивно в случае наследования.