我学习kotlin并且最近发现了一种写kotlin的有趣方式但却无法理解它。
从here
学习代码fun drawerImageLoader(actions: DrawerImageLoaderKt.() -> Unit): DrawerImageLoader.IDrawerImageLoader {
val loaderImpl = DrawerImageLoaderKt().apply(actions).build()
DrawerImageLoader.init(loaderImpl)
return loaderImpl
}
class DrawerImageLoaderKt {
...
}
为什么drawerImageLoader
在课外定义?为什么不能在班级内companion object
区内?
此外,.()
在DrawerImageLoaderKt.()
中的含义是什么?
答案 0 :(得分:4)
该函数在类外定义,为DrawerImageLoader.IDrawerImageLoader
对象提供某种工厂,因此它不受具体实例的约束。
语法DrawerImageLoaderKt.()
定义了Lambda with Receiver,我在此帖子中描述了How to create nested function callbacks like anko - DSL syntax Kotlin
带有Receiver的 Lambda 使我们能够在其正文中的函数文字的接收者(此处为:DrawerImageLoaderKt
)上调用方法,而不需要任何特定限定符(这就是{{{}的调用者1}}会做)。这与扩展函数非常相似,在扩展函数中也可以访问扩展中的接收者对象的成员。
答案 1 :(得分:4)
哦,嘿,这是我的图书馆:)
drawerImageLoader
函数被定义为包级别函数,因此可以在不加前缀的情况下调用它(如果它是实例或object
方法,则必须这样做)。当您调用它时,它会为您提供以下语法(请参阅代码here):
override fun onCreate() {
super.onCreate()
drawerImageLoader {
set {
...
}
cancel {
...
}
}
}
如果它是普通或伴侣对象,它会看起来像这样,我相信这会让一个不太好的DSL:
override fun onCreate() {
super.onCreate()
SomeClass.drawerImageLoader {
set {
...
}
cancel {
...
}
}
}
至于其参数的类型,@ s1m0nw1已经主要回答了那个部分here,但是我只会添加一些。
它是一个带接收器的lambda,它将你置于lambda内DrawerBuilderKt
的范围内,你将传递给drawerImageLoader
函数。由于此类具有set
,cancel
和placeholder
方法,因此可以在lambda中使用这些方法。