我正在尝试为领域对象构建一组提供程序。 这是我尝试构建的示例结构:
接口:
interface IDataProvider<out T : RealmObject> {
fun getRealmObject(): T
}
基类提供程序类,带有用于类型化提供程序实例化的伴随函数:
open abstract class BaseProvider<out T : RealmObject> constructor(protected val context: Context?) : IDataProvider<T> {
companion object {
fun <T : RealmObject, E : BaseProvider<T>> create(context: Context?): E {
if (something) {
return SomeChildProviderProvider(context)
} else {
throw TypeNotSupportedException()
}
}
}
}
这是一个儿童班:
class SomeChildProvider(context: Context?) : BaseProvider<ChildRealmModel>(context){
override fun getRealmObject(): ChildRealmModel {
throw UnsupportedOperationException("not implemented")
}
}
我遇到的问题就行了
return SomeChildProviderProvider(context)
类型不匹配。 要求:E。 发现:SomeChildProvider。
我无法弄清楚为什么它没有看到E实际上是SomeChildProvider。 谢谢。
P.S。我知道我可以把它投到E,但在我看来,在这种情况下不应该需要它。也许我错过了这里显而易见的东西,或者可能缺乏Kotlin知识。
UPDATE1: 在第一个答案之后,我们已经意识到上面的代码没有多大意义,因为我们必须定义一种返回的提供程序并将其传递给create方法。最初的想法是create方法返回一些BaseProvider子类型。以下是我为支持最初想法所做的更改:
IDataProvider
interface IDataProvider {
fun execute(realm: Realm)
fun createModel(realm: Realm): RealmObject
}
BaseProvider
open abstract class BaseProvider constructor(protected val context: Context?) : IDataProvider {
override fun execute(realm: Realm) {
realm.executeTransaction { r ->
createModel(r)
}
}
companion object {
fun create(context: Context?): IDataProvider {
if (something) {
return ChildProvider(context)
} else {
throw TypeNotSupportedException()
}
}
}
}
ChildProvider
class ChildProvider(context: Context?) : BaseProvider(context) {
override fun createModel(realm: Realm): ChildRealmModel {
var realmObject = realm.createObject(ChildRealmModel ::class.java)
//object property initialization
return realmObject
}
}
UI调用
BaseProvider.create(context).execute(realm)
尽管createModel方法返回RealmObject,但它的实例将是ChildRealmModel。我不喜欢的是,如果我们需要其他地方的精确模型,我们必须检查实例类型并进行转换。
答案 0 :(得分:1)
您的代码不一致。
在函数声明中,您承诺返回E
,这是BaseProvider<T>
的子类型,可由用户在呼叫站点上选择。
但是在实现中,您返回SomeChildProviderProvider
,这当然是BaseProvider<T>
的子类型,但仍然可以与用户选择的E
完全无关。
一个例子:
class AnotherChildProvider : BaseProvider<ChildRealmModel>(context) {...}
val x = BaseProvider.create<ChildRealmModel, AnotherChildProvider>(context)
x
的类型是什么?根据函数签名,它必须是AnotherChildProvider
。但是在函数内部返回SomeChildProviderProvider
,不能将其转换为AnotherChildProviderProvider
。