【问题标题】:Kotlin type mismatchKotlin 类型不匹配
【发布时间】:2018-03-08 22:05:27
【问题描述】:

我对泛型类型、子类型和它们之间的不匹配有疑问。我有特定的结构类和接口。我会告诉你,请解释为什么会出现类型不匹配。

假设我正在准备我的 MVP 框架并且我有以下接口和类:

这是最高的抽象

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

    fun detachView()

    fun onDestory() {

    }
}

抽象类包含Presenter的具体方法和实现

abstract class AbstractPresenter<V : AbstractView> : Presenter<V>, LifecycleObserver {

    private var viewReference: WeakReference<V?>? = null

    protected abstract fun onAttached(view: V)

    final override fun attachView(view: V) {
        viewReference = WeakReference(view)
        onAttached(view)
    }

    final override fun detachView() {
        viewReference?.clear()
        viewReference = null
        onDetached()
    }

    protected open fun onDetached() {
    }
}

合同

interface DashboardContract {

    interface View : AbstractView {

    }

    abstract class Presenter : AbstractPresenter<View>(){

    }
}

最后

class DashboardPresenter : DashboardContract.Presenter() {

    override fun onAttached(view: DashboardContract.View) {
    }
}

AbstractView 而言,它看起来更简单。只有接口AbstractView。在合同DashboardContract.View 扩展AbstractView 接口和我的DashboardActivity 实现这个DashboardContract.View 接口。

class DashboardActivity : BaseActivity(), DashboardContract.View { ... }

所以当我在DashboardActivity 中创建DashboardPresenter 作为属性并创建方法fun getPresenter() : Presenter&lt;AbstractView&gt; 然后我得到Type mismatch error 为什么?不是Presenter&lt;AbstractView&gt; 的子类型吗?

fun getPresenter() : AbstractPresenter<AbstractView> {
        return dashboardPresenter // The type is DashboardPresenter
    }

让我们看一下Java代码:

我正在看反编译 Kotlin 的 Java 代码。我把它放在下面。这就是Presenter 的样子:

public interface Presenter {
   void attachView(@NotNull AbstractView var1);

   void detachView();

   void onDestory();

   @Metadata(...)
   public static final class DefaultImpls {
      public static void onDestory(Presenter $this) {
      }
   }
}

我认为如果我在 Kotlin 中使用泛型类,我也会在 java 中获得泛型类。我错了。

AbstractPresenter 给出:

public abstract class AbstractPresenter implements Presenter, LifecycleObserver {
   private WeakReference viewReference;

   protected abstract void onAttached(@NotNull AbstractView var1);

   public final void attachView(@NotNull AbstractView view) {
      Intrinsics.checkParameterIsNotNull(view, "view");
      this.viewReference = new WeakReference(view);
      this.onAttached(view);
   }

   public final void detachView() {
      WeakReference var10000 = this.viewReference;
      if(this.viewReference != null) {
         var10000.clear();
      }

      this.viewReference = (WeakReference)null;
      this.onDetached();
   }

   protected void onDetached() {
   }

   public void onDestory() {
      DefaultImpls.onDestory(this);
   }
}

合同

public interface DashboardContract {
   @Metadata(...)
   public interface View extends AbstractView {
   }

   @Metadata(...)
   public abstract static class Presenter extends AbstractPresenter {
   }
}

DashboardPresetner:

public final class DashboardPresenter extends Presenter {

   protected void onAttached(@NotNull View view) {
      Intrinsics.checkParameterIsNotNull(view, "view");
   }

   // $FF: synthetic method
   // $FF: bridge method
   public void onAttached(AbstractView var1) {
      this.onAttached((View)var1);
   }
}

【问题讨论】:

    标签: android kotlin kotlin-generics


    【解决方案1】:

    您必须将DashboardContract 中的Presenter 的父级更改为使用AbstractView 而不是View

    abstract class Presenter : AbstractPresenter<AbstractView>()
    

    我不确定为什么不允许您使用 View,这可能是一个缺陷 在 Kotlin 的递归类型检查中。看看相应的 java 代码是什么并继续调查可能会很有趣。

    【讨论】:

    • 感谢您的回答,很抱歉耽搁了。我还在调查。我不确定您的意思是 Presenter 的父级 - Presenter 是最高抽象。我看一下对应的java代码,我就放题了。
    • 啊,是的,我指的是DashboardContract 中的Presenter 类。
    • 是的,它有效。但现在我必须手动将AbstractView 转换为DashboardContract.View,因为DashboardPresenter 类保留AbstractionView 而不是DashboardContract.View。我还在我的问题中添加了 Java 代码。
    猜你喜欢
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 2023-03-16
    • 1970-01-01
    相关资源
    最近更新 更多