Kotlin / api-guidelines

Best practices to consider when writing an API for your library

Home Page:https://kotl.in/api-guide

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Operator overloads as member or extension functions

LVMVRQUXL opened this issue · comments

Accordingly to the section Use member and extension functions appropriately, only properties, overrides and accessors should be members. But what about operator overloads?

For example, considering the following NotEmptyString class, if we would like to overload the plus operator for concatenating them, should we declare the overload as a member or as an extension function?

class NotEmptyString(private val value: String) {
    init {
        require(value.isNotEmpty()) { "String shouldn't be empty." }
    }
    
    /*
     * First case - member function.
     * The main advantage is that consumers don't have to import the function for using it.
     * We can also access declarations available only in that class.
     */
    operator fun plus(other: NotEmptyString): NotEmptyString = NotEmptyString(value + other.value)
    
    override fun toString(): String = value
}

/*
 * Second case - extension function.
 * This the way suggested by the Kotlin API guidelines to declare a function that is not part of the "very" core API
 * (because this is not an override, an accessor or a property of the receiver class).
 * But importing this operator function when writing 'NotEmptyString + NotEmptyString' feels less convenient...
 */
operator fun NotEmptyString.plus(other: NotEmptyString): NotEmptyString = NotEmptyString("$this$other")

fun main() {
    val hello = NotEmptyString("hello")
    val world = NotEmptyString(" world")
    println(hello + world) // hello world
}

Overloading operators may be an exception that should be declared as a member function...