Intereting Posts
Изображение не отображается в Recyclerview с помощью Glide Эффективный способ добавления строк, разделенных запятой Метод Kotlin inline не видим, если не расширять класс тип проверки котлин несовместимые типы Обработчик аннотации Kotlin-Kapt не работает с maven Как сделать активность размытой, когда она идет фон? RxJava как создать наблюдаемый из подписки Классы класса Kotlin, которые наследуют классы Java, также наследуются от Any? Использование Kotlin в библиотеке Android, распространяемой как AAR Дезертициализация поля, которое может быть одним из двух типов данных с использованием Moshi Подстановочные знаки, общие для Kotlin для параметра Как исправить ошибку Dagger 2? … не может быть предоставлено '? RxKotlin collectInto () MutableList с использованием ссылок на методы Случайное переопределение: следующие объявления имеют одну и ту же подпись JVM Уведомлять наблюдателя, когда элемент добавлен в список LiveData

Отражающая функция вызова и использование параметров по умолчанию

Учитывая следующую функцию

fun function(x: Int = 12) { println("x = $x") } 

Как я могу использовать отражение, чтобы вызвать его, не указав x (или каким-то образом используя значение по умолчанию, а не жестко кодируя его)?

Вы можете использовать callBy , который учитывает значения по умолчанию:

 ::function.callBy(emptyMap()) // is just function() 

Все будет беспорядочно, если у вас много параметров без значений по умолчанию:

 fun foo(a: Int, b: String = "") {} val ref = ::foo val params = ref.parameters ref.callBy(mapOf(params[0] to 1)) // is just foo(1) 

Это будет еще более скучно, если ваша функция является функцией-членом типа не-объекта, или его функцией расширения, или это функция расширения для типа в качестве функции-члена другого типа не-объекта.

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

 fun <R> KFunction<R>.callNamed(params: Map<String, Any?>, self: Any? = null, extSelf: Any? = null): R { val map = params.entries.mapTo(ArrayList()) { entry -> parameters.find { name == entry.key }!! to entry.value } if (self != null) map += instanceParameter!! to self if (extSelf != null) map += extensionReceiverParameter!! to extSelf return callBy(map.toMap()) } 

Применение:

 fun String.foo(a: Int, b: String = "") {} fun foo(a: Int, b: String = "") {} class Foo { fun bar(a: Int, b: String = "") {} fun String.baz(a: Int, b: String = "") {} } ::foo.callNamed(mapOf("a" to 0)) String::foo.callNamed(mapOf("a" to 0), extSelf = "") Foo::bar.callNamed(mapOf("a" to 0), Foo()) // function reference don't work on member extension functions Foo::class.declaredFunctions.find { it.name == "baz" }!!.callNamed(mapOf("a" to 0), Foo(), "")