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

我在https://github.com/antoniolg/Kotlin-for-Android-Developers上学习Android开发人员Kotlin关于Anko的示例代码(本书)

我在DayForecast(HashMap(it))之前添加了一行var myMap=it ,我认为app会崩溃,因为parseList的定义是parseList(parser: (Map<String, Any?>) -> T) ,我可以只分配一个函数parseList.But应用程序可以正确运行,为什么?

我修改了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) }) 

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

这是高阶函数的一个例子)。

在你的例子中,你正在传递一个lambda表达式

 .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

你也可以使用合格的返回语法显式地从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" } 

在你的例子中,签名有一个通用的参数(类型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! 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)