Reputation: 3339
I have the following Java class I'm trying to convert to Kotlin that uses generics.
abstract class MvpViewHolder, M, V : View?>(itemView: View) : RecyclerView.ViewHolder(itemView) {
public abstract class MvpViewHolder<P extends BasePresenter> extends RecyclerView.ViewHolder {
protected P presenter;
public MvpViewHolder(View itemView) {
super(itemView);
}
public void bindPresenter(P presenter) {
this.presenter = presenter;
presenter.bindView(this);
}
public void unbindPresenter() {
presenter = null;
}
}
Here is my Kotlin attempt
abstract class MvpViewHolder<P : BasePresenter>(itemView: View) : RecyclerView.ViewHolder(itemView) {
protected var presenter: P? = null
fun bindPresenter(presenter: P?): Unit {
this.presenter = presenter
presenter?.bindView(this)
}
fun unbindPresenter(): Unit {
this.presenter = null
}
}
I'm particularly running into a problem with the generics. It turns out that in Kotlin it's simply not enough to do MvpViewHolder<P : BasePresenter>
as Kotlin requires that we pass in the 2 type arguments for BasePresenter (whose implementation I put below)
However, if I need to pass in the type arguments for BasePresenter then my method signature would then look like this
`abstract class MvpViewHolder<P : BasePresenter<*, *>>(itemView: View) : RecyclerView.ViewHolder(itemView) {`
This does not help me however, because in presenter.bindView(this)
I get a type error of Required: Nothing, Found: MvpViewHolder
I could also get more specific and pass in
MvpViewHolder<P: BasePresenter<M, V>, M, V>
but then that would mean that wherever I call MvpViewHolder, I then also have to include 2 extra type parameters. Not only will that be tedious to deal with now having to maintain, but it just makes me sad.
How can I either get rid of the error when I use BasePresenter<,> or avoid having to pass in 3 type parameters into my MvpViewHolder class, just so I can define P as a BasePresenter
abstract class BasePresenter<M, V> {
var model: M? = null
var view: WeakReference<V>? = null
fun setM(model: M?): Unit {
this.model = model
if (setupDone()) {
updateView()
}
}
fun bindView(view: V) {
this.view = WeakReference(view)
}
fun unbindView() {
this.view = null
}
abstract fun updateView()
fun view(): V? {
return if (view == null) null else view?.get()
}
fun setupDone(): Boolean {
return view() != null && model != null
}
}
Upvotes: 0
Views: 903
Reputation: 2545
Change abstract class to the following code
abstract class MvpViewHolder<P :BasePresenter<P,MvpViewHolder<P>>>(itemView: View) : RecyclerView.ViewHolder(itemView) {
protected var presenter: P? = null
fun bindPresenter(presenter: P) {
this.presenter = presenter
presenter.bindView(this)
}
fun unbindPresenter() {
presenter = null
}
}
Upvotes: 1