Комплексный тип 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>
он принимает и генерирует свой универсальный тип, поэтому он не может принимать подтип или супертип в своем универсальном параметре вместо требуемого.