Kotlin 类型不匹配(接口未正确解析)

Kotlin Type Mismatch (interface is not resolved properly)

我正在使用 Ktorm 并尝试为我的 table 创建一个抽象和通用的 DAO。最后我得到了一个类型不匹配但我没有看到我错在哪里:

BaseEntity 是实体 class 的接口,id 为:

interface BaseEntity<T: Entity<T>>: Entity<T> {
    val id: Int
}

用户(ORM class):

interface User: BaseEntity<User>

IdTable(一个以 int id 作为主键的 table):

open class IdTable<T : BaseEntity<T>>(tableName: String) : Table<T>(tableName) {
    val id = int("id").primaryKey().bindTo { it.id }
}

用户(SQL table):

object Users : IdTable<User>("users")

BaseDao:

open class BaseDao<E : BaseEntity<E>>(private val es: EntitySequence<E, IdTable<E>>)

UserDao 实现了 BaseDao:

class UserDao(val es: EntitySequence<User, IdTable<User>>) : BaseDao<User>(es)

现在,正如 Ktorm 文档中所述,我创建了一个像

这样的 EntitySequence
val Database.users get() = this.sequenceOf(Users)

我想创建一个 UserDao:

userDao = UserDao(database.users)

但是我明白了

Type mismatch.
Required:
EntitySequence<User, IdTable<User>>
Found:
EntitySequence<User, Users>

但是 UsersIdTable<User> 类型,因为它继承自它。为什么编译器不知道?

我不了解 Ktorm,所以我不会在这方面帮助您,但您的问题是由 type variance 引起的。是的,你是对的,Users 可以安全地用作 IdTable<User>。但这并不意味着 EntitySequence<User, Users> 可以用作 EntitySequence<User, IdTable<User>>EntitySequenceT 类型参数是 不变的 这意味着它不能安全地向上或向下转换。

为了安全地将 EntitySequence<User, Users> 转换为 EntitySequence<User, IdTable<User>>T 必须 协变 ,因此必须将其标记为out 参数。但事实并非如此。

事实上,通过查看 EntitySequence 的定义,我认为 T could/should 被标记为 out。然后你就可以毫无问题地做你需要做的事。也许这只是Ktorm中的一个bug/oversight

如果我是正确的并且 T 可能是协变的,那么通过进行未经检查的转换来解决您的问题应该也是安全的:

userDao = UserDao(database.users as EntitySequence<User, IdTable<User>>)

一个 long-term 解决方案是将此报告给 Ktorm 开发人员 - 请他们将 T 标记为 out.