【问题标题】:Kotlin generics inheritance - Type mismatchKotlin 泛型继承 - 类型不匹配
【发布时间】:2016-12-25 00:11:10
【问题描述】:

我正在尝试为领域对象构建一组提供程序。 这是我尝试构建的示例结构:

界面:

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。 谢谢。

附:我知道我可以将它转换为 E,但在我看来,在这种情况下不需要它。也许我在这里遗漏了一些明显的东西,或者可能缺乏 Kotlin 知识。

更新1: 在第一个答案之后,我们意识到上面的代码没有多大意义,因为我们必须定义一种返回提供者并将其传递给 create 方法。最初的想法是 create 方法返回某种类型,即 BaseProvider 子类型。以下是我为了支持最初的想法而进行的更改:

IDataProvider

interface IDataProvider {
    fun execute(realm: Realm)
    fun createModel(realm: Realm): RealmObject
}

基础提供者

 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()
            }
        }
    }
}

子提供者

class ChildProvider(context: Context?) : BaseProvider(context) {
    override fun createModel(realm: Realm): ChildRealmModel {
        var realmObject = realm.createObject(ChildRealmModel ::class.java)
        //object property initialization
        return realmObject
    }
}

界面调用

BaseProvider.create(context).execute(realm)

虽然createModel 方法返回RealmObject,但它的实例将是ChildRealmModel。我不喜欢的是,如果我们在其他地方需要精确的模型,我们必须检查实例类型并进行转换。

【问题讨论】:

  • 能否请您更具体地说明您的不满意之处?我看不到您必须“检查实例类型并在我们需要精确模型时进行转换”。

标签: android generics inheritance kotlin


【解决方案1】:

您的代码不一致。

在函数声明中,您承诺返回E,它是BaseProvider&lt;T&gt; 的子类型,用户可以在调用站点上选择。

但在实现中,您返回SomeChildProviderProvider,它当然是BaseProvider&lt;T&gt; 的子类型,但仍然可以与用户选择的E 完全无关。

一个例子:

class AnotherChildProvider : BaseProvider<ChildRealmModel>(context) {...}

val x = BaseProvider.create<ChildRealmModel, AnotherChildProvider>(context)

x 的类型是什么?根据函数签名,它必须是AnotherChildProvider。但是在函数内部你返回SomeChildProviderProvider,它不能被转换为AnotherChildProviderProvider

【讨论】:

  • 你是对的。我已经很累了,没有意识到使用 create 方法我必须定义返回提供者的类型。但是,我最初的想法是拥有一个通用接口。提供者来实现该接口和一些静态方法,我可以在其中决定要实例化哪个提供者。我的解决方案在已编辑问题的 UPDATE 1 中,但我仍然对此不满意。
猜你喜欢
  • 2020-10-18
  • 1970-01-01
  • 2017-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-27
相关资源
最近更新 更多