Как составить карту общих интерфейсов потребителей с параметрами контравариантности типов? - PullRequest
0 голосов
/ 25 октября 2019

Я пытаюсь реализовать твердый подход к моему приложению в Android. Я следую этому посту , чтобы разработать универсальный интерфейс для реализации в классе Adapter для выбора провайдера аутентификации пользователя. В моем конструкторе мне требуется карта с возможными реализациями для нескольких поставщиков аутентификации (Facebook, Google и т. Д.), Но когда я строю карту, компилятор жалуется на «несовместимые типы» объектов.

Я пытался ввести некоторые ковариационные и контравариантные операторы в универсальных интерфейсах и использовал «проекцию звезды» на карту, но компилятор не работает, когда составляет карту или когда я вызываю функцию интерфейса в моих реализациях.

Это интерфейс, который расширяет объекты параметров до реализаций

interface IQuery<TResult>

Это пример объекта параметров

data class FacebookLoginEvent (
        val requestCode: Int,
        val resultCode: Int,
        val data: Intent?
): IQuery<String>

И это интерфейс дляреализации для служб проверки подлинности

interface IQueryService<TQuery: IQuery<TResult>, TResult> {
    fun execute(query: TQuery): TResult
}

Пример реализации поставщика проверки подлинности

class FacebookSignInFlow(): IQueryService<FacebookLoginEvent, String> {
    override fun execute(query: FacebookLoginEvent): String {
        // Do something with the event
    }
}

Составной класс с перечислителем для выбора поставщика, выполняющего проверку подлинности

class CredentialSignInFlow(
        private val signInFlowProviders: Map<
                CredentialSignInFlowProvider,
                IQueryService<IQuery<String>, String>
        >
) {
    fun signIn(provider: CredentialSignInFlowProvider, query: IQuery<String>){
        signInFlowProviders.getValue(provider).execute(query)
    }
}

enum class CredentialSignInFlowProvider{
    FacebookProvider,
    GoogleSilentProvider,
    GoogleProvider
}

Когда я отправляю карту, компилятор говорит, что

Type inference failed. Expected type mismatch: inferred type is Map<CredentialSignInFlowProvider, FacebookSignInFlow> but Map<CredentialSignInFlowProvider, IQueryService<IQuery<String>, String>> was expected

Воткод для построения графа объекта

CredentialSignInFlow(mapOf(
    CredentialSignInFlowProvider.FacebookProvider to FacebookSignInFlow()
))

1 Ответ

0 голосов
/ 25 октября 2019

Проблема в том, что ваш CredentialSignInFlow ожидает в точности Map<CredentialSignInFlowProvider, IQueryService<IQuery<String>, String>> класса и не применяет никаких наследников IQuery<String> в универсальном сервисе.

Я вижу здесь только одно решение - сделать CredentialSignInFlow универсальнымтоже.

class CredentialSignInFlow<T : IQuery<String>>(
        private val signInFlowProviders: Map<
                CredentialSignInFlowProvider,
                IQueryService<T, String>
                >
) {
    fun signIn(provider: CredentialSignInFlowProvider, query: T){
        signInFlowProviders.getValue(provider).execute(query)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...