我使用 Kotlin 和 Mongo(使用 KMongo ),并且我有多个模型,例如 UserEntityMovieEntity 等。它们每个都使用特定的 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 忘记了泛型的类型 TBaseDao<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 的方法中导出也具体化了。


评论关闭
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!