mardi 5 février 2019

Simple service locator with generic type parameters in Kotlin

I followed these instructions to create a simple service locator, adapted to Kotlin and simplified even more for the purpose of my question:

object ServiceLocator {

    @JvmStatic
    fun getService(serviceName: String): Any {
        val service = lookupService(serviceName)

        if (service != null) {
            return service
        }

        throw UnknownServiceException()
    }

    private fun lookupService(serviceName: String): Any? {
        if (serviceName.equals("MyService")) {
            return MyService()
        }

        return null
    }
}

I can use it as follows:

val myService = ServiceLocator.getService("MyService") as IMyService

The problem I have with this is myService is of type Any. I'd prefer it if getService returned the actual type instead. Ideally, I'd like to use it like so:

val myService = ServiceLocator.getService<IMyService>()

Or, if that's not possible, something like this would be fine:

val myService = ServiceLocator.getService(IMyService::class)

I can't figure out how to make the generic type parameters work. This is what I tried:

@JvmStatic
fun <T> getService(): T {
    val service = lookupService<T>()

    if (service != null) {
        return service
    }

    throw UnknownServiceException()
}

private fun <T> lookupService(): T? {
    if (T::class == IMyService::class) {
        return MyService()
    }

    return null
}

The compiler is complaining about two things:

  1. On T::class, it complains "Cannot use 'T' as reified type parameter. Use a class instead."
  2. On return MyService(), it says "Type mismatch. Required: T? Found: MyService"

Aucun commentaire:

Enregistrer un commentaire