我使用 Kotlin 和 Mongo(使用 KMongo ),并且我有多个模型,例如 UserEntity、MovieEntity 等。它们每个都使用特定的 Dao 类来执行(实际上)相同的方法。因此,我试图通过使用应该具有这些方法的 BaseDao 来避免任何重复。
因此,我将通用库中的特定实体传递为:
class UserDao : BaseDao<UserEntity>() { ... }
该基类实现通用方法如下:
open class BaseDao<T: Any>() {
fun get(id: String): T? {
return getCollection().findOneById(id)
}
fun save(entity: T): T {
return getCollection().save(entity)
}
fun delete(id: String) {
getCollection().deleteOneById(id)
}
...
}
但是,getCollection() 方法出现问题:
private inline fun <reified T: Any> getCollection(): MongoCollection<T> {
return MongoDb.getDatabase().getCollection<T>()
}
每次我调用它时都会出现编译错误:
Type inference failed: Not enough information to infer parameter T in
inline fun <reified T : Any> getCollection(): MongoCollection<T#1 (type parameter of app.api.db.dao.BaseDao.getCollection)>
Please specify it explicitly.
我找不到正确的方法来做到这一点。我已经检查了这些线程,但我没有使它工作:Generic class type usage in Kotlin & Kotlin abstract class with generic param and methods which use type param .
问题:
如何实现这个通用的BaseDao,它应该获取每个子Dao的任何集合?
请您参考如下方法:
JVM 忘记了泛型的类型 T在BaseDao<T: Any>()在运行时,这就是类型推断失败的原因。解决这个问题的方法是在 BaseDao 的构造函数中传递 T 的 KClass:
open class BaseDao<T: Any>(val kClass: KClass<T>) {
...
}
在此之后,为您的具体化函数提供一个接受“KClass”的参数:
private inline fun <reified T: Any> getCollection(val kClass: KClass<T>): MongoCollection<T> {
return MongoDb.getDatabase().getCollection<T>()
}
我不知道有什么方法可以在不通过 KClass 的情况下执行此操作作为函数的参数,但这应该可以工作,就像通用 T 一样可以从提供的 kClass 派生。 `
另一种方法是使 BaseDao 中的所有方法都具有具体化泛型,并将泛型放在类上。
open class BaseDao() {
inline fun <reified T: Any> get(id: String): T? {
return getCollection().findOneById(id)
}
inline fun <reified T: Any> save (entity: T): T {
return getCollection().save(entity)
}
inline fun <reified T: Any> delete(id: String) {
getCollection().deleteOneById(id)
}
...
}
这样通用T可以从调用 getCollection 的方法中导出也具体化了。




