mardi 5 février 2019

How can I compare an instance of a class to a type of interface?

I'm attempting to implement a simple service locator in Kotlin, based on this article, except I want to use generic type parameters. I'm also trying to avoid inlining the functions with reified type parameters because that requires everything to be public.

This class is responsible for caching instances of located services:

class Cache {
    private val services: MutableList<Any> = mutableListOf()

    fun <T> getService(serviceClass: Class<T>): T? {
        val service = services.firstOrNull { s -> s::class.java == serviceClass }

        if (service != null) {
            return service as T
        }

        return null
    }

    fun addService(service: Any) {
        services.add(service)
    }
}

This is how the cache is being called:

cache.getService(IMyService::class)

It returns null everytime, regardless of whether it contains an instance of MyService or not. The problem is on s::class.java == serviceClass, because at runtime the cache contains an instance MyService, and MyService::class.java is not equivalent to IMyService::class (nor is MyService::class - I tried that too).

I tried modifying the getService method like so:

fun <T> getService(): T? {
    val service = services.firstOrNull { s -> s is T }

    if (service != null) {
        return service as T
    }

    return null
}

On s is T, the compiler complains "Cannot check for instance of erased type: T". How can I make this work without inlining, which would require the list of services to be made public?

Aucun commentaire:

Enregistrer un commentaire