Простой сервисный локатор с параметрами общего типа в Котлине - PullRequest
0 голосов
/ 05 февраля 2019

Я следовал этим инструкциям , чтобы создать простой сервисный локатор, адаптированный к Kotlin и еще более упрощенный для целей моего вопроса:

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
    }
}

Я могу использовать его следующим образом:

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

У меня проблема с myService типа Any.Я бы предпочел, чтобы getService возвращал реальный тип.В идеале я хотел бы использовать это так:

val myService = ServiceLocator.getService<IMyService>()

Или, если это невозможно, что-то вроде этого было бы хорошо:

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

Я не могу понятькак заставить работать параметры общего типа.Вот что я попробовал:

@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
}

Компилятор жалуется на две вещи:

  1. На T::class, он жалуется "Невозможно использовать 'T' в качестве параметра типа reified.Вместо этого используйте класс. "
  2. На return MyService() написано" Несоответствие типов. Обязательно: T? Найдено: MyService "

1 Ответ

0 голосов
/ 05 февраля 2019

Чтобы получить доступ к типу, T, во время выполнения без необходимости передавать класс (например, ServiceLocator.getService(IMyService::class)), вы должны использовать параметр типа reified .Неявно это означает, что вы должны изменить свои методы на встроенные функции .Делая это, вы можете обновить свой код ниже:

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

    if (service != null) {
        return service
    }

    throw UnknownServiceException()
}

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

    return null
}
...