我对泛型类型,子类型和它们之间的不匹配有疑问。我有特定的结构类和接口。我会告诉你,请解释我为什么会出现类型不匹配。
假设我正在准备我的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 { ... }
因此,当我在DashboardPresenter
创建DashboardActivity
作为属性并创建方法fun getPresenter() : Presenter<AbstractView>
时,我得到Type mismatch error
为什么?不是Presenter<AbstractView>
的子类型?
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);
}
}
答案 0 :(得分:0)
您必须更改Presenter
中DashboardContract
的父级,才能使用AbstractView
代替View
:
abstract class Presenter : AbstractPresenter<AbstractView>()
我不确定为什么不允许你使用View
,这可能是一个缺陷
在Kotlin的递归类型检查中。看看相应的java代码是什么并继续从中进行调查可能会很有趣。