Комплексный тип MutableMap

Я немного запутался здесь.

Итак, у меня есть mutableMap типа

val converters = mutableMapOf<String, Pair<KFunction<ElemBase>, x>>()

где я не могу понять x

Мне нужно добавить к этой карте несколько пар на основе конструктора и метода, таких как:

converters["Camera"] = ::Camera to Structure::convertCamera

Где первое поле - это ссылка на расширение конструктора ElemBase, такие как:

Camera : ElemBase

а второй метод на Structure класс со ссылкой на обнуляемый ElemBase учебный класс:

fun convertCamera (dest: KMutableProperty0<Camera?>)

когда x

KFunction<*> работает, но мне нужно что-то более конкретное, где Receiver и аргумент определены.

Я попробовал пару попыток, таких как

KFunction<Structure.(KProperty1<Structure, ElemBase>) -> Unit>

или же

KFunction<(KMutableProperty0<ElemBase>) -> Unit>

или же

KFunction<Structure.(KMutableProperty0<ElemBase?>) -> Unit>

Я всегда получаю сообщение об ошибке, когда пытаюсь что-то добавить к converters

Error:(276, 9) Kotlin: Type inference failed: Cannot infer type parameter V in operator inline fun <K, V> MutableMap<K, V>.set(key: K, value: V): Unit
None of the following substitutions
receiver: MutableMap<String, Pair<Int, KFunction<Structure.(KMutableProperty0<ElemBase?>) -> Unit>>>  arguments: (String,Pair<Int, KFunction<Structure.(KMutableProperty0<ElemBase?>) -> Unit>>)
receiver: MutableMap<String, Pair<KFunction0<Camera>, KFunction2<Structure, @ParameterName KMutableProperty0<Camera>, Unit>>>  arguments: (String,Pair<KFunction0<Camera>, KFunction2<Structure, @ParameterName KMutableProperty0<Camera>, Unit>>)
can be applied to
receiver: MutableMap<String, Pair<Int, KFunction<Structure.(KMutableProperty0<ElemBase?>) -> Unit>>>  arguments: (String,Pair<KFunction0<Camera>, KFunction2<Structure, @ParameterName KMutableProperty0<Camera>, Unit>>)

но пока не везет

Интересно отметить, что если я назначу ::Camera to Structure::convertCamera к переменной я получаю следующий тип:Pair<KFunction0<ElemBase>, KFunction2<Structure, @ParameterName KMutableProperty0<ElemBase>, Unit>>

Но у меня нет KFunction0 ни KFunction2... Что за черт?

Изменить: нашел это

Edit2: если я вручную импортирую KFunction0 а также KFunction2 кажется, что они больше не жалуются на них. Но если я нажму на них, это не может решить..

Я пытался импортировать вручную оба, KFunction0 а также KFunction2, копируя тип, который я видел, когда я назначаю пару var и похоже, что это работает:

val converters = mutableMapOf<String, Pair<KFunction0<Camera>, KFunction2<Structure, KMutableProperty0<Camera>, Unit>>>()

Но не соответствующий ElemBase версия:

val converters = mutableMapOf<String, Pair<KFunction0<ElemBase>, KFunction2<Structure, KMutableProperty0<ElemBase>, Unit>>>()

Error:(277, 9) Kotlin: Type inference failed: Cannot infer type parameter V in operator inline fun <K, V> MutableMap<K, V>.set(key: K, value: V): Unit
None of the following substitutions
receiver: MutableMap<String, Pair<KFunction0<ElemBase>, KFunction2<Structure, KMutableProperty0<ElemBase>, Unit>>>  arguments: (String,Pair<KFunction0<ElemBase>, KFunction2<Structure, KMutableProperty0<ElemBase>, Unit>>)
receiver: MutableMap<String, Pair<KFunction0<Camera>, KFunction2<Structure, @ParameterName KMutableProperty0<Camera>, Unit>>>  arguments: (String,Pair<KFunction0<Camera>, KFunction2<Structure, @ParameterName KMutableProperty0<Camera>, Unit>>)
can be applied to
receiver: MutableMap<String, Pair<KFunction0<ElemBase>, KFunction2<Structure, KMutableProperty0<ElemBase>, Unit>>>  arguments: (String,Pair<KFunction0<Camera>, KFunction2<Structure, @ParameterName KMutableProperty0<Camera>, Unit>>)

Хотя я до сих пор не понимаю, что происходит KFunction*почему они, кажется, не существуют, хотя однажды импортированные вручную, компилятор принимает их

На случай, если дизайн пахнет, я портирую немного кода на C++ и хотел бы придерживаться исходной структуры, если это возможно

Edit3: хорошо, я, вероятно, изменит дизайн, но я хотел бы узнать, что происходит в любом случае, ради любопытства

1 ответ

Решение

Если вы запишите следующий код в IntelliJ:

val map = mutableMapOf("Camera" to (::Camera to Structure::convertCamera))

Затем вы можете вызвать намеренное действие "явно указать тип" в назначении или нажать "Ctrl + Q" на переменной, чтобы вызвать информацию о ее типе, которая выводится.

Это дает вам следующее:

val map: MutableMap<String, Pair<KFunction0<Camera>, KFunction2<Structure, @ParameterName(name = "dest") KMutableProperty0<Camera?>, Unit>>>

KFunction0 а также KFunction2 Вот некоторые классы, в которые Kotlin компилирует типы функций (те, которые имеют 0 и 2 параметра, соответственно). Из книги " Котлин в действии":

Стандартная библиотека Kotlin определяет серию интерфейсов, соответствующих разному количеству аргументов функции: Function0<R> (эта функция не принимает аргументов), Function1<P1, R> (эта функция принимает один аргумент) и так далее. Каждый интерфейс определяет один метод invoke, и вызов его будет выполнять функцию.

Вместо этого вы можете заменить их типами функций и удалить некоторую ненужную информацию, например:

val map: MutableMap<String, Pair<() -> Camera, (Structure, KMutableProperty0<Camera?>) -> Unit>>

Так как вы хотели ElemBase быть в типе вместо конкретного Camera типа, вы можете сделать это:

val map3: MutableMap<String, Pair<() -> ElemBase, (Structure, KMutableProperty0<Camera?>) -> Unit>>

Тем не менее, вы не можете изменить KMutableProperty0<Camera> в KMutableProperty0<ElemBase>, так как этот тип является инвариантом, и это будет нарушать присваивание в вашем примере. Как MutableList<T>он принимает и генерирует свой универсальный тип, поэтому он не может принимать подтип или супертип в своем универсальном параметре вместо требуемого.

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