复杂的MutableMap类型

时间:2018-02-14 20:17:49

标签: types kotlin signature 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 ......到底是什么?

修改:找到this

Edit2:如果我手动导入KFunction0KFunction2,它似乎不再抱怨它们了。但如果我点击它们,就无法解决..

我尝试手动导入KFunction0KFunction2,复制我在将对分配给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 个答案:

答案 0 :(得分:2)

如果您在IntelliJ中记下以下代码:

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

然后,您可以明确地调用&#34;指定类型&#34;意图对作业采取行动,或按&#34; Ctrl + Q&#34;在变量上显示其推断的类型信息。

这将为您提供以下内容:

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

KFunction0KFunction2这里是Kotlin编译函数类型的一些类(分别具有0和2个参数的类)。来自Kotlin in Action书:

  

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>,因为此类型为invariant,因此这会破坏您示例中的分配。就像MutableList<T>一样,它接受并生成其泛型类型,因此它不能在其泛型参数中接受子类型或超类型,而不是所需的类型。