0

I'm doing small library in Kotlin which handles presenter during configuration changed. I create presenter store class where I going to keep the presenters. I use generic class but I have problem but maybe I'll show you the code.

interface AbstractStore {
    fun clear()
    fun <V : AbstractView> put(key: String, presenter: Presenter<V>)
    fun <V : AbstractView> get(key: String): Presenter<V>? 
}

and implementation of Abstract Store

class PresenterStore : AbstractStore {

    private val mMap = HashMap<String, Presenter<AbstractView>>()

    override fun <V : AbstractView> put(key: String, presenter: Presenter<V>) {
        mMap[key] = presenter   // problem is here. I can't do this in that way.
    }

    override fun <V : AbstractView> get(key: String): Presenter<V>? {
        return mMap[key]
    }

    /**
     * Clears internal storage that Presenters are no longer used.
     */
    override fun clear() {
        mMap.forEach { (_, presenter) -> presenter.onDestory() }
        mMap.clear()
    }
}

I got problem with the put method. The message what I get:

Error:(12, 10) Type inference failed: Cannot infer type parameter V in operator inline fun <K, V> MutableMap<K, V#1 (type parameter of kotlin.collections.set)>.set(key: K, value: V#1): Unit
None of the following substitutions
receiver: MutableMap<String, Presenter<AbstractView>>  arguments: (String,Presenter<AbstractView>)
receiver: MutableMap<String, Presenter<V#2 (type parameter of com.xxxx.mvp.presenter.PresenterStore.put)>>  arguments: (String,Presenter<V#2>)
can be applied to
receiver: HashMap<String, Presenter<AbstractView>>  arguments: (String,Presenter<V#2>)

I don't get it what is going on but If I change it the method to

mMap[key] = presenter as Presenter<AbstractView> then works with warning

Unchecked cast: Presenter<V> to Presenter<AbstractView>

Is there any possibilities to keep method without casting? Why Kotlin doesn't know that Presenter is a generic class with subtype of AbstractView?

1 Answer 1

1

Instead of making the two methods independently generic, use a class type parameter like so:

interface AbstractStore <V : AbstractView> {
    fun clear()
    fun put(key: String, presenter: Presenter<V>)
    fun get(key: String): Presenter<V>? 
}

Then, in the implementation, define a concrete type:

class PresenterStore : AbstractStore<ConcreteView> {

    override fun put(key: String, presenter: Presenter<ConcreteView>) {
        mMap[key] = presenter
    }

    override fun get(key: String): Presenter<ConcreteView>? {
        return mMap[key]
    }

    private val mMap = HashMap<String, Presenter<ConcreteView>>()
}

Now it works and is completely type safe.

Sign up to request clarification or add additional context in comments.

1 Comment

Thx. The simple the best.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.