1

I'm learning kotlin and has recently spotted an interesting way of writing kotlin but can't really understand it.

taken the code I'm learning from here

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

class DrawerImageLoaderKt {
    ...
}

why should drawerImageLoader defined outside of class? why can't be in the class and within companion object block?

Also, what does .() mean in DrawerImageLoaderKt.()?

user1865027
  • 3,505
  • 6
  • 33
  • 71

2 Answers2

4

The function is defined outside the class to provide some kind of factory for DrawerImageLoader.IDrawerImageLoader objects, so it's not bound to concrete instances.

The syntax DrawerImageLoaderKt.() defines a Lambda with Receiver, which I described in this thread: How to create nested function callbacks like anko - DSL syntax Kotlin

A Lambda with Receiver enables us to call methods on a receiver (here: DrawerImageLoaderKt) of the function literal in its body without any specific qualifiers (That's what a caller of drawerImageLoader will do). This is very similar to extension functions, where it’s also possible to access members of the receiver object inside the extension.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
4

Oh hey, this is my library :)

The drawerImageLoader function is defined as a package level function so that it can be invoked without prefixing it (as you'd have to do if it was an instance or object method). This gives you the following syntax when you call it (see the code here):

override fun onCreate() {
    super.onCreate()

    drawerImageLoader {
        set {
            ...
        }
        cancel {
            ...
        }
    }
}

If it was in a regular or companion object, it would look like this instead, which I believe makes for a less nice DSL:

override fun onCreate() {
    super.onCreate()

    SomeClass.drawerImageLoader {
        set {
            ...
        }
        cancel {
            ...
        }
    }
}

As for the type of its parameter, @s1m0nw1 already mostly answered that part here, but I'll add just a bit more.

It's a lambda with a receiver, which places you in the scope of a DrawerBuilderKt inside the lambda that you're passing to the drawerImageLoader function. Since this class has set, cancel, and placeholder methods, these become available to use inside the lambda.

zsmb13
  • 85,752
  • 11
  • 221
  • 226
  • wow! great lib!! I've finished the basics tutorial in learning kotlin and am now reading your repo to get more understanding on how to write in kotlin – user1865027 Dec 02 '17 at 01:50