【问题标题】:Kotlin Pass in a type that implements a parameterized interfaceKotlin 传入实现参数化接口的类型
【发布时间】:2018-05-04 13:07:11
【问题描述】:

我有以下工作 Java 代码,但是当我将其转换为 Kotlin 时,代码无法编译

Java代码

public interface Presenter<V> {
   void attachView(V view);
}

实现上述接口的抽象类

public abstract class BasePresenter<T> implements Presenter<T> {
    @Override
    public void attachView(T view) {
        this.view = view;
    }
}

采用实现上述接口的 Type 参数的抽象类

public abstract class PresenterActivity<P extends Presenter> extends BaseActivity {

    protected P presenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (presenter != null) {
        presenter.attachView(this);
        }
    }
}

扩展 BasePresenter 的类

public class FooPresenter extends BasePresenter<BarView> {
    ...
}

一个扩展 PresenterActivity 的类

public class SomeActivity extends PresenterActivity<FooPresenter> implements BarView {
   ....
}

Kotlin 从上面的 Java 代码转换而来的代码

interface Presenter<in V> {
    fun attachView(view: V)
}

实现上述接口的抽象类

abstract class BasePresenter<V> : Presenter<V> {
    override fun attachView(view: V) {
        this.view = view
    }
}

采用Type参数实现上述接口的抽象类,不确定下面的&lt;P : Presenter&lt;Any&gt;&gt;是否是正确的表达方式

abstract class PresenterActivity<P : Presenter<Any>> : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (presenter != null) {
            presenter!!.attachView(this)
        }
   }
}

扩展 BasePresenter 的类

class FooPresenter : BasePresenter<BarView>() {
    ....
}

一个扩展 PresenterActivity 的类

class SomeActivity : PresenterActivity<FooPresenter>(), BarView {
    ....
}

Kotlin 类 PresenterActivity 给出以下编译错误 错误:(9, 44) 类型参数不在其范围内:应该是 'Presenter&lt;Any&gt;' 的子类型

这意味着FooPresenter 不会被识别为Presenter&lt;Any&gt; 的子类型

我假设Presenter&lt;V&gt;Presenter&lt;Any&gt; 的子类,我感觉我错了

【问题讨论】:

    标签: java android types kotlin


    【解决方案1】:

    您的 Java 代码实际上存在类型安全问题:PresenterActivity&lt;P extends Presenter&gt; 使用了 raw type,而当您稍后编写 presenter.attachView(this) 时,您不知道是否可以附加 this,但是原始类型意味着编译器不会警告你。 Kotlin 不允许你这样隐藏它。

    我假设Presenter&lt;V&gt;Presenter&lt;Any&gt; 的子类,我感觉我错了

    in 实际上意味着Presenter&lt;V&gt;Presenter&lt;Any&gt;超级 类型,而不是子类型。请参阅https://kotlinlang.org/docs/reference/generics.html(或搜索协变和逆变,有很多关于 Stack Overflow 和其他方面的解释,虽然 Scala 比 Kotlin 更多,但想法是一样的)。

    我认为最简单的解决方案是

    // concrete subclasses must extend V
    abstract class PresenterActivity<V, P : Presenter<V>> : BaseActivity() {
       ... presenter!!.attachView(this as V)
    }
    

    class SomeActivity : PresenterActivity<BarView, FooPresenter>(), BarView {
        ....
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-08
      • 1970-01-01
      • 2019-03-22
      • 1970-01-01
      • 2010-11-11
      相关资源
      最近更新 更多