No, data
classes don't have any specific representation in type system and cannot be distinguished from regular classes (similar question).
You can, however, require the methods a data
class with certain number of components has using an interface (actually it will be a marker interface on data
classes).
Here's an example for data
classes with two components:
interface Data2<T1, T2> {
operator fun component1(): T1
operator fun component2(): T2
fun copy(t1: T1, t2: T2): Data2<T1, T2>
}
toString
, hashCode
and equals
can be called on any type anyway.
Then just mark your data
class with the interface:
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
function is not completely type-safe because Kotlin doesn't have self type (and no way to require interface implementations to be subtype of a specific type), but if you only mark your data
classes with it, it should work (see another option below).
Another drawback is that you lose default parameters of copy
method and have to call it with all the parameters specified:
val d = myD2.copy(newValue, myD2.component2())
Another option is to define these interfaces as Data2<T1, T2, out Self>
, class Impl(...): Data2<..., Impl>
, and make copy
return Self
, but it won't make it any better if you use the interface as Data2<SomeType, SomeType, *>
.