伴侣对象块和kotlin类外的趣味之间的区别?

我正在学习kotlin,最近发现了写kotlin的一个有趣的方式,但是不能真正理解它。

采取了我从这里学习的代码

fun drawerImageLoader(actions: DrawerImageLoaderKt.() -> Unit): DrawerImageLoader.IDrawerImageLoader { val loaderImpl = DrawerImageLoaderKt().apply(actions).build() DrawerImageLoader.init(loaderImpl) return loaderImpl } class DrawerImageLoaderKt { ... } 

为什么要在类的外面定义drawerImageLoader ? 为什么不能在class级和companion object块内?

另外,在DrawerImageLoaderKt.().()是什么意思?

该函数在类的外部定义,为DrawerImageLoader.IDrawerImageLoader对象提供某种工厂,所以它不绑定到具体的实例。

DrawerImageLoaderKt.()语法定义了一个带有ReceiverLambda ,我在这个线程中描述了: 如何创建像anko这样的嵌套函数回调 – DSL语法Kotlin

带有ReceiverLambda使我们能够在函数文本的接收方(这里是DrawerImageLoaderKt )上调用方法,而不需要任何特定的限定符(这就是drawerImageLoader的调用方所要做的)。 这与扩展函数非常相似,也可以在扩展中访问接收者对象的成员。

噢,这是我的图书馆:)

drawerImageLoader函数被定义为一个包级别的函数,这样它就可以被调用,而不用加前缀(如果它是一个实例或者object方法,你必须这样做)。 当你调用它的时候,这给你下面的语法(参见这里的代码):

 override fun onCreate() { super.onCreate() drawerImageLoader { set { ... } cancel { ... } } } 

如果它是在一个普通的或伴随的对象,它会看起来像这样,而我相信使一个不太好的DSL:

 override fun onCreate() { super.onCreate() SomeClass.drawerImageLoader { set { ... } cancel { ... } } } 

至于其参数的types,@ s1m0nw1已经大部分回答了这个部分,但是我会多添加一些。

这是一个带有接收器的lambdaexpression式,它将您DrawerBuilderKt在传递给drawerImageLoader函数的lambdaexpression式中的DrawerBuilderKt范围内。 由于这个类有setcancelplaceholder方法,所以可以在lambda里面使用。