Параметр ковариантной функции в Котлине

Я хочу реализовать функцию, которая необязательно принимает класс Activity и перенаправляет на него. Если класс не указан, будет использоваться значение по умолчанию.

В Java я бы сделал

public void onComplete(@Nullable Class<? extends Activity> redirectTarget) {
    if (redirectTarget == null) redirectTarget = DefaultActivity.class;
    ContextCompat.startActivity(context, new Intent(context, redirectTarget), null);
}

Теперь я попробовал следующее в Котлине:

fun <T : Activity> onComplete(redirectTarget: Class<in T> = DefaultActivity::class.java) {
    ContextCompat.startActivity(context, Intent(context, redirectTarget), null)
}

Я думал, что in T примет любые подклассы T в параметре, но в приведенном выше примере я получаю предупреждение о том, что

Type missmatch. 
Expected: Class <in T>
Found: Class<DefaultActivity>

Как реализовать функцию, которая принимает любой класс Activity?

Как создавать пользовательские общие типы в Python (50/100 дней Python)
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Помимо встроенных типов, модуль типизации в Python предоставляет возможность определения общих типов, что позволяет вам определять типы, которые могут...
0
0
156
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

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

Допустим, у вас есть функция:

fun <T> print(toPrint: T) = println(toPrint.toString())

Вы можете вызвать эту функцию следующим образом:

print<Int>(1)

Все хорошо.

Но допустим, вы хотите иметь параметр String по умолчанию, когда пользователь не хочет указывать аргумент `toPrint'. Следуя вашему подходу, вы должны сделать:

fun <T> print(toPrint: T = "") = println(toPrint.toString())

В мире, где это законно, что произойдет, если вы вызовете функцию, указав тип, но не аргумент? Например.:

print<Int>()

Тип параметра по умолчанию не соответствует типу на сайте вызова.

Так как же решить вашу проблему?
Оказывается, вам даже не нужна общая функция, как вы могли бы сделать:

fun onComplete(redirectTarget: Class<out Activity> = DefaultActivity::class.java) {
    ContextCompat.startActivity(context, Intent(context, redirectTarget), null)
}

я не знаю, почему это так, но вам просто нужно передать это Class<T>. измените свою функцию на это.

fun <T : Activity> onComplete(redirectTarget: Class<in T> = DefaultActivity::class.java as Class<T>) {
    ContextCompat.startActivity(context, Intent(context, redirectTarget), null)
}

я просто добавляю as Class<T> в конце onComplete входных данных

Обновлять:

вы также можете написать функцию расширения

fun Class<out Activity>?.onComplete() {
    ContextCompat.startActivity(context, Intent(context, this ?: DefaultActivity::class.java), null)
}

и вы можете использовать его так

MainActivity::class.java.onComplete()

и для класса по умолчанию

null.onComplete()

Попробуй это:

fun onComplete(redirectTarget:Class<out Activity> = DefaultActivity::class.java){
    ContextCompat.startActivity(context, Intent(context, redirectTarget), null)
}

Другие вопросы по теме