function - 扩展 lambda 接受错误的参数
问题描述
我认为扩展 lambda 要求您传入正确的参数,但在下面的示例中我似乎没有这样做。
open class Base {
open fun f() = 1
}
class Derived : Base() {
override fun f() = 99
}
fun Base.g(): Int { return f()}
fun Base.h(xl: Base.() -> Int): Int { return xl()}
fun main() {
val b: Base = Derived() // Upcast
println(b.g())
println(b.h { f()}) // [1]
}
我知道 Base.h 采用一个以 Base 对象作为参数的函数。但是第 [1] 行显示它接受 f(),这是一个不带参数的函数。我一直在努力思考这个问题,并在它前面加上了 this.f() 并且它仍然有效。不服气,我修改代码如下:
open class Base {
open fun f() = 1
}
class Derived : Base() {
override fun f() = 99
}
fun Base.g(): Int { return f()}
fun Base.h(xl: (Base) -> Int): Int { return xl(Base())}
fun test(i:Int) = 1
fun main() {
val b: Base = Derived() // Upcast
println(b.g())
println(b.h { test(1) })
}
此代码有效。我已经运行它来验证。正如你所看到的,bh() 接受 test(),它接受一个 Int。这与 Base.h() 采用 Base 的事实相反。
你能解释一下吗?感谢您的阅读。
解决方案
注意传入的函数周围的大括号!他们改变了一切。
在第二个代码中,b.h { test(1) }
没有将函数传递test
给b.h
. 传递test
给的语法b.h
是b.h(::test)
,这确实会产生您所期望的错误。
b.h { test(1) }
传递一个以 a 作为参数的函数(一个lambda 表达式)Base
,忽略该参数,调用test(1)
并返回结果。您基本上是将一个看起来像这样的函数传递给b.h
:
fun foo(p: Base) = test(1)
您可能想知道 Kotlin 是如何知道Base
您根本没有Base
在调用中写下这个词的。好吧,它可以只看 的声明b.h
,并看到它{ test(1) }
必须带一个参数Base
。
第一个代码片段有点不同,因为在这种情况下b.h
接受 a Base.() -> Int
。Base.() -> Int
表示接收器类型为Base
的函数func
,即可以像 一样调用的函数someBaseObject.func()
。func
将此与将对象作为参数的函数进行比较Base
,可以像func(someBaseObject)
.
再次,{ f() }
没有传递函数f
。它是一个 lambda 表达式,除了调用之外什么都不做f
。但是在这种情况下,f
它本身可以传递给b.h
( b.h(Base::f)
),因为它是一个接收器类型为Base
!的函数。你可以做someBaseObject.f()
,不是吗?传递 lambda 类似于传递这样声明的扩展函数(您只是“包装”f
在另一个函数中):
fun Base.foo() = f()
由于函数的接收者是Base
,因此您可以访问lambda 中Base
作为接收者(例如)的其他函数。f
您还可以明确指定接收者(即this
)。
推荐阅读
- python - 重新导入 TKINTER
- pandas - CSV 中的重复行应使用 python 数据框相加
- javascript - 为生产构建时未定义反应
- reactjs - 我已经为文本框创建了一个模板组件,它在 Angular 中运行良好,现在我如何在反应中使用来获得发射值?
- performance - 在移动应用程序模拟器上进行负载测试的方法(无需连接到真实设备)
- neo4j - Graphlytic 桌面错误 Neo4j Graph is not running. Please start Neo4j Graph 然后重启 Graphlytic
- javascript - 为什么我会出现未处理的异常:在颤振应用程序中键入“TextFormField”错误?
- dart - 任何元素数据类型的星号后缀 (*)(分析器 >= 0.40.0)
- reactjs - 找不到带有自定义 cra 模板的 package.json
- sql-server - 如何解决此 SQL Server 代理错误?