Hello, fellow Kotliners. Below is a short version...
# language-proposals
e
Hello, fellow Kotliners. Below is a short version of a proposal I'd like to add to the KEEP, depending on the result of this discussion. Proposal: change the way extension functions are defined and referenced for companion objects and add ability to define "static extension functions" for Java classes (solves the most-voted YouTrack issue: https://youtrack.jetbrains.com/issue/KT-11968). Short summary: 1. Allow defining extension functions for classes with a
fun Class::function
syntax. 2. Automatically create companion objects when creating extension functions for classes. --- Currently, defining extension functions for companion objects involves some boilerplate:
Copy code
class Foo {
  companion object
}

fun Foo.Companion.bar() = ...
For Java classes, it's not possible to define extension functions since there's no concept of companion objects. However, it's possible to reference static functions:
Copy code
fun parseInts(values: List<String>) = values.map(Integer::parseInt)
Since the
::
syntax is already used for referencing functions for companion, member and Java's static functions, it could also be used for defining extension functions:
Copy code
fun List<String>::parseInts() = map(Integer::parseInt)
For Java, this would generate code similar to what is generated for extension functions of instances. For Kotlin, it would do two things: • Create the companion object for the class being extended, unless it already exists. (Current version requires declaring
companion object
inside the class to be extended. Besides being confusing when the companion object is empty, it's not intuitive since there's no need for any special declarations when defining non-companion extension functions) • Add the extension function to the companion object. --- Primary use case would be for factory methods. A real-world example using Exposed:
Copy code
// commonMain/src/kotlin/User.kt

data class User(
  val name: String,
  val email: String
) {
  companion object // <-- confusing
}

// jvmMain/src/kotlin/User.kt

fun User.Companion.fromResultRow(resultRow: ResultRow): User = ...

fun findUsers() = Users.selectAll().map(User::fromResultRow)
This would work because it's pure Kotlin, but it would require declaring
companion object
only to allow adding extension functions. It doesn't express any intention and is inconsistent with the way non-companion extension functions work, as they require no additional declarations on the extended class. However, the main motivation of automatically creating companion objects is to hide this Kotlin-only detail when defining the extension function, allowing extension functions for Java classes. With the proposal, it would look like this:
Copy code
// commonMain/src/kotlin/User.kt

data class User(
  val name: String,
  val email: String
)

// jvmMain/src/kotlin/User.kt

fun User::fromResultRow(resultRow: ResultRow): User = ...

fun findUsers() = Users.selectAll().map(User::fromResultRow)
Which would also work if
User
was a class witten in Java. The alternative for Java today is to write top-level functions. A good example is jackson-module-kotlin, which adds a
kotlinObjectMapper
factory function. While it works, using this approach for every DTO in a system would pollute the top-level namespace, making autocompletion less effective. Another option would be to create a
ResultRow.toUser
extension function instead, but that would also pollute the namespace of a very general class.
👍 1