Нет, классы data
не имеют какого-либо конкретного представления в системе типов и их нельзя отличить от обычных классов (похожий вопрос).
Однако вы можете потребовать, чтобы методы класса data
с определенным количеством компонентов имели интерфейс (фактически это будет интерфейс маркера для классов data
).
Вот пример для классов data
с двумя компонентами:
interface Data2<T1, T2> {
operator fun component1(): T1
operator fun component2(): T2
fun copy(t1: T1, t2: T2): Data2<T1, T2>
}
toString
, hashCode
и equals
в любом случае можно вызывать для любого типа.
Затем просто отметьте свой класс data
интерфейсом:
data class Impl(val i: Int, val s: String): Data2<Int, String>
val d: Data2<Int, String> = Impl(1, "2")
val (c1, c2) = d
val copy = d.copy(-1, d.component2())
copy
не является полностью безопасным типом, потому что Kotlin не t имеют собственный тип (и нет способа требовать, чтобы реализации интерфейса были подтипом определенного типа), но если вы пометите им только свои data
классы, это должно работать (см. другой вариант ниже).
Другой недостаток заключается в том, что вы теряете параметры по умолчанию метода copy
и должны вызывать его со всеми указанными параметрами:
val d = myD2.copy(newValue, myD2.component2())
Еще один вариант — определить эти интерфейсы как Data2<T1, T2, out Self>
, class Impl(...): Data2<..., Impl>
и заставить copy
возвращать Self
, но это не улучшит ситуацию, если вы будете использовать интерфейс как Data2<SomeType, SomeType, *>
.
person
hotkey
schedule
05.06.2016