Intereting Posts
Почему Котлин не требует попыток и уловки явно Перегрузка равна BigDecimal в Котлине Массив байтов в Json с использованием топлива и результатов Как реорганизовать представление, чтобы разрешить фильтрацию элементов, привязанных к наблюдаемомуArrayList, внутри приложения tornadofx Почему я не могу использовать @PublishedApi для typealias? Исключение Null Pointer, работающее с Map (Kotlin) Maven с Kotlin 1.2: Требуемый класс отсутствовал kotlin / reflection / KDeclarationContainer Почему я не могу сказать: val list = properties.map ((ключ, значение) -> "$ key = $ value") Как написать общий метод расширения в Котлине? Почему я получаю ошибку java.lang.IllegalStateException: экземпляр не инициализирован? Поддержка Base64 для разных уровней API Ошибка переноса подпункта: com.android.dx.cf.code.SimException: local 0007: недействительный Как я могу запустить Kotlin REPL kotlinc-jvm или kotlinc Как избежать частичного покрытия латинскими полями в Котлине Получение параметров формы на сервер Ktor

Как имитировать или достигать отношения IS-A для классов данных Kotlin

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

В разработке программы я использую классы данных для представления списка воспроизведения. в какой-то момент в дизайне я хотел иметь специальный тип Playlist который был EmptyPlaylist .

Я не мог заставить это работать.

Как бы вы достигли этих отношений с Котлином?

В Java я бы просто расширил список Playlist (или, возможно, создал интерфейс / абстрактный класс для их обоих, чтобы наследовать).

Я просто хотел иметь List<Playlist> а не List<Playlist?>

В конце концов, я просто создал объект Playlist , но меня интересует, можно ли создавать иерархии IS-A с классами данных.

UPD: Kotlin Beta добавил ограничения на классы data , поэтому ответ также был обновлен.

  • Классы данных не могут быть абстрактными, открытыми, закрытыми или внутренними;
  • Классы данных могут не распространять другие классы (но могут реализовывать интерфейсы).

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


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

  • Вы можете сделать как TracksPlaylist и EmptyPlaylist реализовать интерфейс Playlist . Это разумно, потому что EmptyPlaylist может не содержать все, что делает Playlist . Это будет выглядеть так:

     public interface Playlist data class TracksPlaylist(val name: String, val tracks: List<Track>) : Playlist data class EmptyPlaylist(val name: String): Playlist 
  • Если вы не хотите, чтобы несколько экземпляров EmptyPlaylist даже существовали, вы можете сделать это val вместо отдельного класса и избежать проверок, просто сравнивая с

     val EMPTY_PLAYLIST = TracksPlaylist("EMPTY", listOf()) 

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

  • Вы можете использовать sealed классы . Это не позволяет использовать классы data , но sealed классы могут соответствовать для построения иерархии классов, подобных этому.

    sealed класс – это абстрактный класс, который может только объявлять его подклассы внутри своего тела. Это дает компилятору гарантии, что они являются единственными подклассами. Пример:

     sealed class Playlist(val name: String) { class Tracks(name: String, val tracks: List<Track>): Playlist(name) class Playlists(name: String, val innerPlaylists: List<Playlist>): Playlist(name) object Empty: Playlist("EMPTY") } 

    После этого вы сможете использовать оператор if без указания ветки else если вы укажете все подклассы и объекты закрытого класса:

     when (p) { is Playlist.Tracks -> { /* ... */ } is Playlist.Playlists -> { /* ... */ } Playlist.Empty -> { /* ... */ } } 

    Однако эта опция требует, чтобы вы hashCode дело с equals , hashCode , toString , copy и componentN самостоятельно, если они вам нужны.