В Kotlin, как вы объявляете класс данных с нулевыми параметрами конструктора?

Скажем, я хочу объявить простой алгебраический тип данных для целых списков:

sealed class IntList data class Cons(val head: Int, val tail: IntList): IntList() data class Nil() : IntList() 

Однако последнее объявление приводит к ошибке

Класс данных должен иметь по крайней мере один параметр первичного конструктора

  1. Почему это ограничение присутствует? Если посмотреть на документацию, то, по-видимому, нет хороших технических причин для того, чтобы требовать, чтобы конструкторы класса данных были не нулевыми.
  2. Можно ли выразить конструкторы с нулевым значением без необходимости писать много шаблонов? Если я изменю последнее объявление на что-то вроде

     sealed class Nil() : IntList() 

    то я теряю свободные реализации hashCode() и equals() которые бесплатно предоставляются с объявлениями data class .

РЕДАКТИРОВАТЬ

Алекс Филатов дал хорошее короткое решение ниже. Очевидно, вам не нужно больше одного экземпляра Nil , поэтому мы можем просто определить одноэлементный объект

 object Nil : IntList() 

Однако, что бы мы сделали, если наши списки были параметризованы параметром типа? То есть, теперь первые две строки нашего определения будут

 sealed class List<A> data class Cons<A>(val head: A, val tail: List<A>): List<A>() 

Мы не можем объявить полиморфный одноэлементный объект Nil который происходит из List<A> для любого A , поскольку мы должны предоставить конкретный тип для A во время объявления. Решение (взятое из этого сообщения ) заключается в объявлении A как параметра ковариантного типа и объявлении Nil как подтипа List<Nothing> следующим образом:

 sealed class List<out A> data class Cons<A>(val head: A, val tail: List<A>): List<A>() object Nil : List<Nothing>() 

Это позволяет нам писать

 val xs: List<Int> = Cons(1, Cons(2, Nil)) val ys: List<Char> = Cons('a', Cons('b', Nil)) 

Solutions Collecting From Web of "В Kotlin, как вы объявляете класс данных с нулевыми параметрами конструктора?"

Поскольку data class без данных не имеет смысла. Использовать object для одиночек:

 object Nil : IntList() 

Вам нужно будет создать обычный класс

 class Nil : IntList() 

и реализовать hashCode() и equals() самостоятельно.

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


Или: вы можете использовать класс объекта (как сказал Алекс Филатов ), который является единственным классом экземпляра. Поскольку вам не нужно состояние для каждого отдельного экземпляра Nil , они могут совместно использовать один.

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

 data class Nil(val _u: Byte = 0) : IntList() 

или

 data class Nil(val _u: Nothing? = null) : IntList()