Почему Kotlin не может выполнять умный приведение между интерфейсом и производным типом от него? - PullRequest
0 голосов
/ 05 июня 2018

У меня есть следующий класс:

abstract class PresenterActivity<S : ViewState, I : ViewIntent> : AppCompatActivity() { 
    open fun initViewIntent(): I {
        return object : ViewIntent{} // type mismatch on this line
    }
}

Я получаю сообщение об ошибке перед компиляцией:

Type mismatch
Required: I
Found: <S, I>

Чтобы исправить эту ошибку перед компиляцией, я приводю объект ViewIntent кI:

abstract class PresenterActivity<S : ViewState, I : ViewIntent> : AppCompatActivity() { 
    open fun initViewIntent(): I {
        @Suppress("UNCHECKED_CAST")
        return object : ViewIntent{} as I
    }
}

Но почему Котлин не может обнаружить, что I должен быть получен из ViewIntent, и умно наложить его?

Ответы [ 3 ]

0 голосов
/ 05 июня 2018

Это потому, что ViewIntent не I.Смотрите пример:

class MyViewIntent : ViewIntent

class MyPresenterActivity : PresenterActivity<..., MyViewIntent>() {
    // inherited from PresenterActivity
    open fun initViewIntent(): ViewIntent {
        return object : ViewIntent{} as MyViewIntent // you see where this breaks
    }
}
0 голосов
/ 25 января 2019

По сути, причина того, что вы делаете, не работает, потому что то, что I является подклассом ViewIntent.Ваш объект также является подклассом ViewIntent.Это совершенно другой подкласс.Актерский состав, который вы делаете, похож на попытку преобразовать StringBuilder в String.

Теперь давайте обсудим, что, по вашему мнению, вы «хотите» сделать, и почему это тоже не работает.Чтобы действительно получить желаемый результат, вам нужно непосредственно создать тип I, например:

return object : I {}

И мы заменили этот I фактическим классом

return object : SomeClass {}

это, конечно, тоже не получится.Необходимо вызвать конструктор SomeClass, а вы этого не делаете.И нет никакого способа узнать, что передать в этот конструктор при использовании универсального типа.

0 голосов
/ 05 июня 2018

Это просто потому, что "I" не обязательно является производным от ViewIntent, а именно от класса ViewIntent.

Вы можете исправить это так:

abstract class PresenterActivity<S : ViewState, I : ViewIntent> : AppCompatActivity() { 
    open fun initViewIntent(): ViewIntent {
        return object : ViewIntent{} 
    }
}

Делать это по-своему действительно небезопасно.

Чтобы понять почему, я думаю, вы должны начать читать это:

https://blog.kotlin -academy.com / kotlin-generics-variance-modifiers-36b82c7caa39

https://kotlinlang.org/docs/reference/generics.html

https://proandroiddev.com/understanding-generics-and-variance-in-kotlin-714c14564c47

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...