Reputation: 765
i have the following working Java code however when i convert it into Kotlin, the code does not compile
Java code
public interface Presenter<V> {
void attachView(V view);
}
Abstract class implementing above interface
public abstract class BasePresenter<T> implements Presenter<T> {
@Override
public void attachView(T view) {
this.view = view;
}
}
Abstract class that takes a Type parameter which implements the interface above
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);
}
}
}
A class extending BasePresenter
public class FooPresenter extends BasePresenter<BarView> {
...
}
A class extending PresenterActivity
public class SomeActivity extends PresenterActivity<FooPresenter> implements BarView {
....
}
Kotlin code converted from above Java Code
interface Presenter<in V> {
fun attachView(view: V)
}
Abstract class implementing above interface
abstract class BasePresenter<V> : Presenter<V> {
override fun attachView(view: V) {
this.view = view
}
}
Abstract class that takes a Type parameter which implements the interface above, am not sure if <P : Presenter<Any>>
below, is the correct expression
abstract class PresenterActivity<P : Presenter<Any>> : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (presenter != null) {
presenter!!.attachView(this)
}
}
}
A class extending BasePresenter
class FooPresenter : BasePresenter<BarView>() {
....
}
A class extending PresenterActivity
class SomeActivity : PresenterActivity<FooPresenter>(), BarView {
....
}
The Kotlin class PresenterActivity
gives the following compilation error
Error:(9, 44) Type argument is not within its bounds: should be sub-type of 'Presenter<Any>
'
this means FooPresenter
is not recorgnised as a sub-type of Presenter<Any>
am assuming Presenter<V>
is a subclass of Presenter<Any>
, i have a feeling am wrong
Upvotes: 2
Views: 1695
Reputation: 170723
Your Java code actually has a type safety problem: PresenterActivity<P extends Presenter>
uses a raw type and when you later write presenter.attachView(this)
you don't know whether you can attach this
, but raw type means the compiler doesn't warn you. Kotlin doesn't let you hide it like this.
am assuming
Presenter<V>
is a subclass ofPresenter<Any>
, i have a feeling am wrong
in
actually means Presenter<V>
is a super-type of Presenter<Any>
, not a subtype. See https://kotlinlang.org/docs/reference/generics.html (or search for covariance and contravariance, there are a lot of explanations on Stack Overflow and otherwise, though more for Scala than Kotlin but the idea is the same).
I think the simplest solution would be something like
// concrete subclasses must extend V
abstract class PresenterActivity<V, P : Presenter<V>> : BaseActivity() {
... presenter!!.attachView(this as V)
}
and
class SomeActivity : PresenterActivity<BarView, FooPresenter>(), BarView {
....
}
Upvotes: 3