【问题标题】:Kotlin typealias of generic supertype with bound type parameter not working for inheritance具有绑定类型参数的泛型超类型的 Kotlin 类型别名不适用于继承
【发布时间】:2018-07-28 17:14:41
【问题描述】:

TL;DR 为什么会这样:

interface SomeInterface
interface Generic <T : SomeInterface> {}
class Self : Generic<Self>, SomeInterface

这不是:

interface SomeInterface
interface Generic <T : SomeInterface> {}
typealias Specified = Generic<Self>
class Self : Specified, SomeInterface

错误:类型参数不在其范围内:应该是的子类型 '一些接口'

错误说它不是正确的子类型,但它是!

这种类型别名的用例来自现实生活中的代码,其中一个超类有 5 个类型参数,每个类型参数都有相当长的名称,我不想用不必要的垃圾邮件污染类头。有任何想法吗?我正在使用 kotlin 1.2.51。

---原来的问题---

MVP 接口:

interface MVPComponent // dagger component 
interface MVPComponentHolder<C : MVPComponent> // implementing class must provide component
interface MVPArgs // args passed from view to presenter on attach
interface MVPView<A : MVPArgs> // MVP View, must provide Args for presenter
interface MVPPresenter<T : MVPView<A>, A : MVPArgs, U : MVPUseCase>
interface MVPUseCase // selected API methods to use in presenter

MVP 的基础片段:

abstract class MVPFragment<F, V, P, A, C>
    : Fragment(), MVPComponentHolder<C>
    where F : V,
          V : MVPView<A>,
          P : MVPPresenter<V, A, *>,
          C : MVPComponent<V>,
          A : MVPArgs {
    // lots of MVP logic
}

MVP 合同:

interface ExampleMVP {
    data class Args(/* ... */) : MVPArgs

    interface View : MVPView<Args> {
        //...
    }
    interface Presenter : MVPPresenter<View, Args, UseCase> {
        //...
    }
    interface UseCase : MVPUseCase<View> {
        //...
    }
}

最终片段:

class ExampleFragment : MVPFragment<
    ExampleFragment,
    ExampleMVP.View,
    ExampleMVP.Presenter,
    ExampleMVP.Args,
    ExampleMVP>(), ExampleMVP.View {
    // final fragment logic
}

但我想使用以下语法:

private typealias SuperFragment = MVPFragment<
        ExampleFragment,
        ExampleMVP.View,
        ExampleMVP.Presenter,
        ExampleMVP.Args,
        ExampleMVP>

class ExampleFragment : SuperFragment(), ExampleMVP.View {
    // final fragment logic
}

我将ExampleFragment 作为MVPFragment 的类型参数传递的原因是因为Dagger 2 必须直接注入到目标类中(在这种情况下不仅仅是FragmentMVPFragment,而是ExampleFragment),或者注入代码不会生成。

MVPFragment 中的注入如下所示:

@CallSuper
override fun onAttach(context: Context) {
    super.onAttach(context)
    component.injectIntoView(this as F) // must be target fragment type (here F)
}

【问题讨论】:

    标签: android generics kotlin mvp type-alias


    【解决方案1】:

    问题是循环依赖引入的:

    class Self : Specified, SomeInterface
    

    如果Self 没有从Specified 继承,它可以工作。

    更改后的示例如下所示。

    interface SomeInterface
    interface Generic <T : SomeInterface> {}
    typealias Specified = Generic<Self>
    class Self : SomeInterface
    

    至于你原来的问题。我不认为你可以完全实现这一点,但必要的类型参数的数量可以像这样减少:

    class ExampleFragment : SuperFragment<ExampleFragment>(), ExampleMVP.View {
        // final fragment logic
    }
    
    private typealias SuperFragment<T> = MVPFragment<
            T,
            ExampleMVP.View,
            ExampleMVP.Presenter,
            ExampleMVP.Args,
            ExampleMVP<ExampleMVP.View, ExampleMVP.Args>>
    

    【讨论】:

    • 对不起我的错误。 Self 不能从 Specified 继承,因为这会产生循环依赖。在您的示例中,我认为这不是必需的。如果是,请提供更详细的示例。我更新了答案中的代码。
    • 用解决大部分问题的解决方案更新了我的答案。
    • 好的,这似乎是这种情况下要走的路
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多