代码之家  ›  专栏  ›  技术社区  ›  xinaiz

具有绑定类型参数的泛型父类型的Kotlin TypeAlias不可用于继承

  •  1
  • xinaiz  · 技术社区  · 6 年前

    为什么这样做有效:

    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
    

    错误:类型参数不在其边界内:应为的子类型 “某些接口”

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

    此类typealias的用例来自于实际代码,其中一个超类有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 因为匕首2必须直接注入目标类(在这种情况下不仅仅是 Fragment MVP-片段 但是 范例片段 否则将不会生成注入代码。

    注入 MVP-片段 如下所示:

    @CallSuper
    override fun onAttach(context: Context) {
        super.onAttach(context)
        component.injectIntoView(this as F) // must be target fragment type (here F)
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Alexander Egger    6 年前

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