是否有一种方法要求泛型类型是Kotlin中的数据类?

以下不起作用,但希望可以帮助你明白我的意思:

class Example<T : DataClass> 

如果你想知道我正在努力完成什么,这是我想到的一个例子:

 class Repository<T> where T : Entity, // Entity defines mutable property 'id' T : DataClass { // assume there is a map here fun add(obj: T) { val copy = obj.copy(id = generateID()) map.put(copy.id, copy) } } 

还是有更好的方法来完成我想要做的?

我有这样的感觉,你真正想要的是,T应该能够复制自己一个新的ID,并有一个ID。 不一定,这是一个数据类。 所以你可以使用一个接口来定义它。

例如:

 interface CopyableWithId<out T> where T: CopyableWithId<T> { fun copy(newId: Long): T val id: Long } data class BarBaz(override var id: Long, var name: String): CopyableWithId<BarBaz> { override fun copy(newId: Long): BarBaz = copy(id = newId) } class Repository<T> where T : CopyableWithId<T>{ val map: MutableMap<Long, CopyableWithId<T>> = HashMap() fun add(obj: T) { val copy = obj.copy(generateID()) map.put(copy.id, copy) } private fun generateID(): Long { return 1L } } 

不, 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> } 

toStringhashCodeequals可以在任何类型上调用。

然后用接口标记你的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 没有自我类型 (也没有办法要求接口实现是特定类型的子类型),但是如果你只用它来标记你的data类,它应该工作(见另一个下面的选项)。

另一个缺点是你失去了copy方法的默认参数,必须用指定的所有参数来调用它:

 val d = myD2.copy(newValue, myD2.component2()) 

另一个选择是将这些接口定义为Data2<T1, T2, out Self>class Impl(...): Data2<..., Impl> ,并使copy返回Self ,但不会使它更好如果您将接口用作Data2<SomeType, SomeType, *>