有没有办法要求泛型类型成为Kotlin中的数据类?

8 generics kotlin data-class

以下不起作用,但希望能帮助您理解我的意思:

class Example<T : DataClass>
Run Code Online (Sandbox Code Playgroud)

如果你想知道我想要完成什么,这就是我想到的一个例子:

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)
  }

}
Run Code Online (Sandbox Code Playgroud)

或者有更好的方法来完成我想要做的事情吗?

JB *_*zet 6

我觉得你真正想要的是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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 是否担心这会导致无限循环?如果我们不能真正调用`super.copy`,它不会递归调用copy吗?为了确定起见,我将我的命名为“copyID”。 (2认同)

hot*_*key 5

不,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>
}
Run Code Online (Sandbox Code Playgroud)

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())
Run Code Online (Sandbox Code Playgroud)

copyfunction 并不完全类型安全,因为 Kotlin没有 self 类型(并且无法要求接口实现是特定类型的子类型),但如果您只用data它标记您的类,它应该可以工作(请参阅下面的另一个选项)。

另一个缺点是您会丢失copy方法的默认参数,并且必须使用指定的所有参数来调用它:

val d = myD2.copy(newValue, myD2.component2())
Run Code Online (Sandbox Code Playgroud)

另一种选择是将这些接口定义为Data2<T1, T2, out Self>class Impl(...): Data2<..., Impl>和 make copyreturn Self,但如果将接口用作 ,则不会有任何改善Data2<SomeType, SomeType, *>