Functional programming 科特林功能战略模式不';不编译

Functional programming 科特林功能战略模式不';不编译,functional-programming,kotlin,Functional Programming,Kotlin,我试图在一个映射中放置几个函数。这样做的想法是:Map 代码如下: class UserIdQueriesHandler { val strategy: Map<String, KFunction2<@ParameterName(name = "id") String, @ParameterName(name = "options") Array<Options>, Answer>> = mapOf( // the compiler

我试图在一个映射中放置几个函数。这样做的想法是:
Map

代码如下:

class UserIdQueriesHandler {

    val strategy: Map<String, KFunction2<@ParameterName(name = "id") String, @ParameterName(name = "options") Array<Options>, Answer>> =
        mapOf( // the compiler complains here
            "d" to ::debt,
            "p" to ::currentProduct
        )

    fun debt(id: String, options: Array<DebtOptions>): UserDebt = UserDebt(isPresent = true, amount = 0.0)

    fun currentProduct(id: String, options: Array<CurrentProductOptions>): UserProducts = UserProducts(products = emptyList())
}

enum class DebtOptions : Options { BOOL, AMOUNT }

enum class CurrentProductOptions : Options { ALL, PRINT, DIGITAL, ENG, HEB, TM }

data class UserDebt(val isPresent: Boolean, val amount: Double) : Answer
data class UserProducts(val products: List<Int>): Answer
编译器输出:

Type inference failed. Expected type mismatch: 
required:
Map<String, KFunction2<@ParameterName String, @ParameterName Array<Options>, Answer>>
found:
Map<String, KFunction2<@ParameterName String, {[@kotlin.ParameterName] Array  & [@kotlin.ParameterName] Array }, Answer>>
类型推断失败。预期类型不匹配:
必修的:
地图
发现:
地图

策略的类型表示,您放入其中的函数可以接受任何
数组
作为第二个参数,而
债务
当前产品
则不能

最简单的解决方法是将其参数类型更改为
Array
(或
List
;它们可能不需要对其进行变异!),如果传递错误的选项或忽略它们,则在运行时失败


文档中的部分也是相关的。

策略的类型表示,您放入其中的函数可以接受任何
数组
作为第二个参数,而
债务
当前产品
则不能

最简单的解决方法是将其参数类型更改为
Array
(或
List
;它们可能不需要对其进行变异!),如果传递错误的选项或忽略它们,则在运行时失败


文档中的节也是相关的。

由于数组既可以读也可以写,因此其类型参数为。这使得您无法将
数组
分配给类型为
数组
的变量。前者不是后者的子类型,因为它允许您在数组中放置
选项
,而不是
债务选项
,从而导致将此数组引用为
数组
的代码出现问题

如果可以的话,一个解决方案是让函数接受数组

val strategy: Map<String, KFunction2<String, Array<Options>, Answer>> =
        mapOf(
                "d" to ::debt,
                "p" to ::currentProduct
        )

fun debt(id: String, options: Array<Options>): UserDebt = ...

fun currentProduct(id: String, options: Array<Options>): UserProducts = ...

由于
数组既可以读取也可以写入,因此其类型参数为。这使得您无法将
数组
分配给类型为
数组
的变量。前者不是后者的子类型,因为它允许您在数组中放置
选项
,而不是
债务选项
,从而导致将此数组引用为
数组
的代码出现问题

如果可以的话,一个解决方案是让函数接受数组

val strategy: Map<String, KFunction2<String, Array<Options>, Answer>> =
        mapOf(
                "d" to ::debt,
                "p" to ::currentProduct
        )

fun debt(id: String, options: Array<Options>): UserDebt = ...

fun currentProduct(id: String, options: Array<Options>): UserProducts = ...

Array
不协变有点麻烦(这就是为什么我在回答中没有提到它):因为函数在它们的参数中是逆变的,只有逆变类型会进行类型检查,但它在语义上没有意义。我有点如下,但在语义上有什么意义?我的意思是:1。如果将
数组
的所有用法替换为逆变类型(例如
(a)->单位
,那么
策略中的
(选项)->单位
债务中的
(债务选项)->单位
),代码将编译(可能具有更明确的类型注释)。2.然后您就有了
有趣的债务(id:String,options:(DebtOptions)->Unit):UserDebt=…
。3.但是你会如何使用第二个参数呢?
Array
不协变有点像是在转移注意力(这就是为什么我在回答中没有提到它):因为函数在其参数中是逆变的,只有逆变类型会进行类型检查,但在语义上没有意义。我有点如下所述,但是什么在语义上没有意义呢?我的意思是:1。如果将
数组
的所有用法替换为逆变类型(例如
(a)->单位
,那么
策略中的
(选项)->单位
债务中的
(债务选项)->单位
),代码将编译(可能具有更明确的类型注释)。2.然后您就有了
有趣的债务(id:String,options:(DebtOptions)->Unit):UserDebt=…
。3.那么,您将如何使用第二个参数呢?
val strategy: Map<String, (String, Array<Options>) -> Answer> = ...