genericstypes和多态性

我有BaseFragment

  public abstract class BaseFragment extends Fragment implements BaseMvpView { private BasePresenter presenter; protected void syncLifeCycle(BasePresenter presenter) { this.presenter = presenter; this.presenter.onCreate(); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); //noinspection unchecked presenter.onAttachView(this); //it works with a warning } @Override public void onResume() { super.onResume(); presenter.onResume(); } @Override public void onPause() { super.onPause(); presenter.onPause(); } @Override public void onDestroyView() { super.onDestroyView(); presenter.onDetachView(); } @Override public void onDestroy() { super.onDestroy(); presenter.onDestroy(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); presenter.onActivityResult(requestCode, resultCode, data); } } 

和许多类扩展它。 例如MainFragment

  public class MainFragment extends BaseFragment implements MainMvpView { MainPresenter presenter; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); syncLifeCycle(presenter); //presenter.onCreate(); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); //presenter.onAttachView(this); } @Override public void onResume() { super.onResume(); //presenter.onResume(); } @Override public void onPause() { super.onPause(); //presenter.onPause(); } @Override public void onDestroyView() { super.onDestroyView(); //presenter.onDetachView(); } @Override public void onDestroy() { super.onDestroy(); //presenter.onDestroy(); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //presenter.onActivityResult(requestCode, resultCode, data); } } 

我想避免重复每个片段和演示者的生命周期同步代码。 所以我想在BaseFragment实现这个过程。 在Java这一行presenter.onAttachView(this); 工作,但有一个警告“未经检查的调用onAttachView(V) ”(我可以忍受这一点)。 但是Kotlin不允许我这样做

 abstract class BaseFragmentKotlin : Fragment(), BaseMvpView { private var presenter: BasePresenter? = null //... override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) presenter?.onAttachView(this) //Does not work. "Out-projected type 'BasePresenter?' prohibits the use of 'public abstract fun onAttachView(mvpView: V!): Unit defined in com.example.test.BasePresenter" } //... } 

我真的需要建议如何正确地做到这一点。

编辑:

  public class BasePresenterImpl implements BasePresenter { @Nullable public V mvpView; @Override public void onCreate() { } @Override public void onAttachView(V mvpView) { this.mvpView = mvpView; } @Override public void onResume() { } @Override public void onPause() { } @Override public void onDetachView() { mvpView = null; } @Override public void onDestroy() { } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { } } 

这里是整个测试代码https://github.com/AlexNikolaTest/Test/tree/master/app/src/main/java/com/example/mytest

我认为用BaseMvpView替换星形投影会有所帮助

 abstract class BaseFragmentKotlin : Fragment(), BaseMvpView { private var presenter: BasePresenter? = null //... override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) presenter?.onAttachView(this) } //... } 

原因是Kotlin区分了outin型参数(也分别称为协变逆变参数types)。

intypes参数中声明types参数将被generics类使用,即被用作函数的参数,而outtypes参数声明generics类将产生传递types参数的值,即将被使用作为一些函数的返回types。

onAttachView(V mvpView)接受一个逆变types参数,这意味着V不能是任何types(它必须是BaseMvpViewtypes或子types),因为你正在使用这个值。 也就是说,如果V是完全未知的,我们不能安全地读取参数,因为V应该是BaseMvpView一个实例。 但是,如果onAttachView正在产生 (即返回) V对象,那么星形投影将起作用。

希望这可以帮助!

也许你可以这样做

 interface IView interface IPresenter { fun attachView(v: IView) fun detachView() } abstract class BasePresenter : IPresenter { protected var view: V? = null override fun attachView(v: IView) { this.view = v as V } override fun detachView() { view = null } } abstract class BaseFragment

: Fragment(), IView { protected lateinit var presenter: P override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) presenter.attachView(this) } override fun onDestroyView() { super.onDestroyView() presenter.detachView() } } interface TestView : IView { fun doSomething() } interface TestPresenter : IPresenter { fun doSomething() } class TestPresenterImpl : BasePresenter(), TestPresenter { override fun doSomething() { } } class TestFragment : BaseFragment(), TestView { override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) presenter = TestPresenterImpl() presenter.doSomething() } override fun doSomething() { } }

你可以试试这个,那么你也可以在Kotlin中获得未经检查的警告;-)

  if (presenter != null) { val p = presenter as BasePresenter p.onAttachView(this) } 

在你的MainFragment中

  syncLifeCycle(presenter as BasePresenter) 

不知道它是否工作,只是在IntelliJ中玩了一下。 但是由于在编译期间删除了generics,并且将MainPresenter添加到BasePresenter也应该没有问题,所以很有可能会通过。