Why is Mutex.withLock() an extension function?

To understand when I should use extension functions Im asking about the reasoning why withLock() of Mutex is an extension function instead of a normal function. Any convention? Performance difference? I would think that one would only use extension functions to add functions to classes they dont own, but Mutex.withLock() is inside of Mutex.kt so it could be a normal function like lock(). Is there an aim to do as much with extension functions as possible, if so what is the reason (except simply showing that you can do that in Kotlin)?

I think the idea is to only add the essentials to an interface. For something like Mutex that would be lock, unlock, isLocked, etc. So basically everything that needs access to the internal workings of a mutex. withLock doesn’t need that it only requires access to the public functions of a mutex

fun Mutex.withLock(block: () -> Unit) {
    lock()
    block()
    unlock()
}

The actual function probably returns the value of the block and will have some error handling, but this is basically it. You can see that it doesn’t require access to anything internal. That way this is the implementation of withLock regardless of mutex implementation. This can make reasoning about code easier in some cases (you know it will allways call lock/unlock, etc) and also static analisis can be easily done. This is not necessarily the case with a default implementation because this can be changed by the implementing class.
Also and this is the probably more important reasons, it keeps interfaces short and doesn’t fill it with lots of utility functions. Imagine all utility functions of List<T> as a part of the interface. This would just explode the size of the interface unecessarialy. Functions like map, filter, forEach should be a part of every list, but that does not mean that they should be part of the interface. KISS - keep it stupid simple :wink:

1 Like