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

У меня есть набор классов данных, которые разделяют некоторые общие поля. Поэтому в идеале я хотел бы объявить те в супертипе (Message в этом примере) и иметь возможность писать функции, которые работают над супертипом, если им нужен доступ к этим общим полей (messageId в этом примере).

fun operate(m: Message) { use(m.messageId) } 

Я попытался это сделать, расширив классы данных из закрытого класса.

Классы данных могут расширять закрытые классы, но не я не уверен, как / если они могут принимать аргументы, требуемые закрытым классом «супертип».

  1. Расширение обычного класса из закрытого класса компилируется просто отлично.

     sealed class Message(val messageId: String) class Track(val event: String, messageId: String): Message(messageId) 
  2. Однако его изменение в класс данных не компилируется («Основной конструктор класса данных должен иметь только параметры свойства (val / var)».).

     sealed class Message(val messageId: String) data class Track(val event: String, messageId: String): Message(messageId) 
  3. Объявление параметра как свойства также не компилируется («messageId» скрывает член супертипа «Сообщение» и нуждается в переопределении «модификатора»).

     sealed class Message(val messageId: String) data class Track(val event: String, val messageId: String): Message(messageId) 
  4. Открытие свойства супертипа и его переопределение в каждом из базовых классов компилируется отлично:

     sealed class Message(open val messageId: String) data class Track(val event: String, override val messageId: String): Message(messageId) 

В идеале мне хотелось бы что-то близкое к Варианту 2 – это позволяет мне комбинировать лучшее из обоих миров.

В противном случае, по моему мнению, мои варианты – либо выполнять мои собственные функции класса данных (копировать, hashcode, equals и т. Д.) С помощью опции 1, либо жить с компромиссом, открыв свойства супертипа с помощью опции 4.

Варианты 3 и 4 приведут к тому, что messageId содержащее класс, будет дважды. Однажды в новом классе и один раз в своем суперклассе.

Решение заключается в объявлении, но не определении переменной в суперклассе:

 sealed class Message { abstract val messageId: String } data class Track(val event: String, override val messageId: String): Message() 

Это сделает messageId доступным в Message , но делегирует хранилище тем, что его реализует.

Intereting Posts
@PostConstruct не вызывается при использовании Kotlin BeanDefinitionDsl Как расширить класс класса Kotlin или использовать общие для создания простого свойства getter, который будет работать во всех подклассах Number? В TornadoFX, как я могу изменить одно свойство при изменении других свойств? синхронизировать свойства getters / seters ext в buildscript не может быть распознан Gradle Kotlin DSL Приложение Kotlin не показывает мой json-массив Издевательская функция сопутствующего объекта в котлине В Vertx мне нужно перенаправить все HTTP-запросы на один и тот же URL-адрес, но для HTTPS Инструментальные тесты не могут выполняться в библиотечных модулях Android с файлами Kotlin Как получить идентификатор документа для документа Firestore с использованием классов данных kotlin Начало Kotlin для Android Почему var с частным сеттером является инвариантной позицией? Ссылка на значения и методы вызова в типах общих типов Почему не переупорядочивает код в файлах Kotlin в Intellij? Как работать с картами в Котлине