为什么我可以在Kotlin的DayForecast(HashMap(it))之前插入行代码?

时间:2017-11-07 14:16:58

标签: java kotlin

我在https://github.com/antoniolg/Kotlin-for-Android-Developers

了解了针对Android开发者的Kotlin的Anko示例代码(该书)

我在var myMap=it之前添加一行DayForecast(HashMap(it)),我认为应用程序会崩溃,因为parseList的定义是parseList(parser: (Map<String, Any?>) -> T),我只能为parseList指定一个功能。但是应用程序可以正常运行,为什么?

我修改过的ForecastDb.kt

override fun requestForecastByZipCode(zipCode: Long, date: Long) = forecastDbHelper.use {

        val dailyRequest = "${DayForecastTable.CITY_ID} = ? AND ${DayForecastTable.DATE} >= ?"
        val dailyForecast = select(DayForecastTable.NAME)
                .whereSimple(dailyRequest, zipCode.toString(), date.toString())
                .parseList { 
                   var myMap=it
                   DayForecast(HashMap(it)) 
                 }

}

ForecastDb.kt

override fun requestForecastByZipCode(zipCode: Long, date: Long) = forecastDbHelper.use {

        val dailyRequest = "${DayForecastTable.CITY_ID} = ? AND ${DayForecastTable.DATE} >= ?"
        val dailyForecast = select(DayForecastTable.NAME)
                .whereSimple(dailyRequest, zipCode.toString(), date.toString())
                .parseList { DayForecast(HashMap(it)) }

}

DatabaseExtensions.kt

fun <T : Any> SelectQueryBuilder.parseList(parser: (Map<String, Any?>) -> T): List<T> =
        parseList(object : MapRowParser<T> {
            override fun parseRow(columns: Map<String, Any?>): T = parser(columns)
})

1 个答案:

答案 0 :(得分:1)

该功能的签名是parseList(parser: (Map<String, Any?>) -> T)(Map<String, Any?>) -> T)作为参数意味着parseList函数将一个函数类型作为参数,该函数类型具有返回Map<String, Any?>的单个参数(T)的签名。

这是higher-order functions)的一个例子。

在您的示例中,您传递的是lambda expression

.parseList { 
   var myMap=it
   DayForecast(HashMap(it)) 
}

在lambda表达式中,只要返回类型T,就可以执行任何操作。只要在结尾返回类型T,就可以调用多个函数,创建对象,分配变量等等。

为了进一步说明这个想象,我们有一个函数将另一个函数作为参数,它将Int作为参数并返回Int

fun funTakingOne(function: (Int) -> Int): Int {
  return function(1)
}

现在,调用该函数的一种方法是传入一个lambda表达式:

val output = funTakingOne { 
  it + 5
}
println(output)

此处的输出为6

您还可以使用qualified return syntax显式返回lambda中的值。以下是两个相同的电话:

funTakingOne { 
  it + 2 
}
funTakingOne { 
  return@funTakingOne it + 2
}

此lambda表达式的返回值为Int。我们也可以在lambda表达式中做其他事情,只要输出是Int

funTakingOne {
  val someCalculation: Int = expensiveCalculation(it)
  val otherCalculation: Int = otherCalculation(it)
  someCalculation / otherCalculation
}

如果您尝试在此处返回Int以外的任何内容,编译器将因类型不匹配而失败:

// This fails to compile
funTakingOne {
  "oh no, I fail"
}

在您的示例中,签名具有generic参数(类型T)。它与上面的示例类似,只是函数必须返回T类型的东西。

这是另一个人为的例子。将函数作为参数的函数,该函数具有单个String参数并返回类型为T的内容:

fun <T> funReturnT(function: (String) -> T): T {
  return function("Hello World")
}

调用它可能如下所示:

val output = funReturnT {
  "$it! Great day today!"
}
println(output)

此处的输出为Hello World! Great day today!。这里推断的output类型是String,因为我们的lambda表达式返回String(函数的推断类型T)。这与执行以下操作相同:

val output: String = funReturnT {
  "$it! Great day today!"
}
println(output)

如果我们更改output的预期类型,我们将因类型不匹配而导致编译器失败。

// This fails to compile
val output: Int = funReturnT {
  "$it! Great day today!"
}
println(output)