Это то, как я должен подходить к этой проблеме?
ИМХО, да, но с некоторыми изменениями c, перечисленными после.
Как лучше ли сделать свойства связанного значения доступными из запечатанного класса?
Вы можете создавать расширения или функции экземпляра для каждого подкласса.
например
val ContentType.Case2.id: String get() = value.id
Таким образом, вы можете успешно позвонить:
is ContentType.Case2 -> println(content.id)
Как уменьшить размер приложения, сохранив при этом семантику c другого дела?
Вы можете сделать это, сгенерировав только один класс для всех случаев, для которых нужны те же типы, что и для параметров, и использовать Kotlin contracts
для их обработки.
Используя ваш пример, вы можете сгенерировать :
sealed class ContentType {
class Case1(val value: Foo) : ContentType()
class Case2_3(val value: Bar, val caseSuffix: Int) : ContentType()
}
Как видите, классы Case2
и Case3
теперь являются только одним классом, а caseSuffix
определяет, какой из них это.
Теперь вы можете создайте следующие расширения (по одному для каждого случая):
@OptIn(ExperimentalContracts::class)
fun ContentType.isCase1(): Boolean {
contract {
returns(true) implies (this@isCase1 is ContentType.Case1)
}
return this is ContentType.Case1
}
@OptIn(ExperimentalContracts::class)
fun ContentType.isCase2(): Boolean {
contract {
returns(true) implies (this@isCase2 is ContentType.Case2_3)
}
return this is ContentType.Case2_3 && caseSuffix == 2
}
@OptIn(ExperimentalContracts::class)
fun ContentType.isCase3(): Boolean {
contract {
returns(true) implies (this@isCase3 is ContentType.Case2_3)
}
return this is ContentType.Case2_3 && caseSuffix == 3
}
Поскольку вы используете contracts
клиент теперь может использовать их с:
when {
content.isCase1() -> println(content.title)
content.isCase2() -> println(content.id)
content.isCase3() -> println(content.id)
}
Как видите, дальнейшая оптимизация может заключаться в удалении свойства caseSuffix
для случаев с одним суффиксом, чтобы избежать ненужных свойств.