首页 文章

Kotlin Pass是一种实现参数化接口的类型

提问于
浏览
2

我有以下工作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参数实现上面接口的抽象类,不确定下面的 <P : Presenter<Any>> 是否是正确的表达式

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<Any> '的子类型

这意味着 FooPresenter 未被重新识别为 Presenter<Any> 的子类型

假设 Presenter<V>Presenter<Any> 的子类,我有一种感觉是错的

1 回答

  • 3

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

    假设Presenter <V>是Presenter <Any>的子类,我有一种感觉是错的

    in 实际上意味着 Presenter<V>Presenter<Any> 的超类型,而不是子类型 . 请参阅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 {
        ....
    }
    

相关问题