Как применить несколько обобщений в функции с помощью Kotlin - PullRequest
0 голосов
/ 11 мая 2019

Я пытаюсь создать функцию, которая будет анимировать переход от Действия A к Деятельности B, анализируя контекст действия A и класс действия B. Я понял, что будут случаи, когда я хотел бы проанализировать информацию, используя сериализованный классы данных из одного занятия. Поэтому я создал следующую функцию:

fun <T, U> changeActivity(activityAContext : Context, activityB: Class<T>, anim1 : Int, anim2 : Int, extras : Map<String, Class<U>>?=null)
        where T : Activity,
              U : Serializable {
    val activity = activityAContext as Activity
    val intent = Intent(activityAContext , activityB)

    if (extras != null) {

        for ((k, v) in extras) {
            intent.putExtra(k, v)
        }
    }

    activity.overridePendingTransition(anim1, anim2)

    finish()
    startActivity(intent)
}

Однако это не компилируется с ошибкой «Недостаточно информации для вывода параметра U». Я не совсем понимаю, это потому, что я указал, что тип U должен быть классом, который можно сериализировать. Если возможно, не могли бы вы объяснить, почему это происходит и как я могу это решить?

1 Ответ

2 голосов
/ 11 мая 2019

Я не совсем уверен, что вам нужно использовать дженерики здесь.

Вы должны воспользоваться преимуществом полиморфизма и объявить следующее: Напишите метод расширения для класса Activity, чтобы вам не приходилось передавать какой-либо контекст в качестве параметра. Используя полиморфизм, позвольте классу сформировать что-то , то есть Activity, а Map, который вы получите, это Map из String, Serializable, и вы будь более чем хорош.

fun Activity.changeActivity(newActivityClass: Class<Activity>, enteringAnimation: Int, exitingAnimation: Int, extras: Map<String, Serializable>?=null) {
        val intent = Intent(this , newActivityClass)

        extras?.let { it.forEach{ pair -> intent.putExtra(pair.key, pair.value)} }

        overridePendingTransition(enteringAnimation, exitingAnimation)

        finish()
        startActivity(intent)
}

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

changeActivity(DetailActivity::class.java, R.anim.someAnim, R.anim.someOtherAnim, mapOf(Pair("first", myFancySerializableObject)))

В любом случае, я использую для установки дженериков в Kotlin следующий

fun<T: Activity, U: Serializable> myFancyFunction(firstParam: T, second: U) = Unit

Редактировать

Только что протестировал код и попытка вызова этой функции в итоге не компилируется, потому что он ожидает, что первый аргумент будет точно Class из Activity.

В этом случае вы можете использовать новое объявление следующим образом:

fun <A : Activity> Activity.changeActivity(newActivityClass: Class<A>, enteringAnimation: Int, exitingAnimation: Int, extras: Map<String, Serializable>?=null) 

Или, взглянув на конструктор Intent

public Intent(Context packageContext, Class<?> cls) {
    mComponent = new ComponentName(packageContext, cls);
}

Вы можете использовать Class<*> в качестве типа первого аргумента. Без каких-либо дженериков вообще.

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