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>
但是 Users
是 IdTable<User>
类型,因为它继承自它。为什么编译器不知道?
我不了解 Ktorm,所以我不会在这方面帮助您,但您的问题是由 type variance 引起的。是的,你是对的,Users
可以安全地用作 IdTable<User>
。但这并不意味着 EntitySequence<User, Users>
可以用作 EntitySequence<User, IdTable<User>>
。 EntitySequence
的 T
类型参数是 不变的 这意味着它不能安全地向上或向下转换。
为了安全地将 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.
我正在使用 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 文档中所述,我创建了一个像
这样的 EntitySequenceval Database.users get() = this.sequenceOf(Users)
我想创建一个 UserDao:
userDao = UserDao(database.users)
但是我明白了
Type mismatch.
Required:
EntitySequence<User, IdTable<User>>
Found:
EntitySequence<User, Users>
但是 Users
是 IdTable<User>
类型,因为它继承自它。为什么编译器不知道?
我不了解 Ktorm,所以我不会在这方面帮助您,但您的问题是由 type variance 引起的。是的,你是对的,Users
可以安全地用作 IdTable<User>
。但这并不意味着 EntitySequence<User, Users>
可以用作 EntitySequence<User, IdTable<User>>
。 EntitySequence
的 T
类型参数是 不变的 这意味着它不能安全地向上或向下转换。
为了安全地将 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.