Companion object and function extension


#1

Hello,

One of my favorite feature in Kotlin is function extension. I especially like the fact that one can add extension function to a Companion object.

Example:

fun Int.Companion.random(max: Int): Int {
	return ThreadLocalRandom.current().nextInt(max)
}

However, some objects in the standard library do not have Companion, making it impossible to add an extension this way.

Example, the Boolean class:

fun Boolean.Companion.random(): Boolean { // Wrong ! Boolean Companion does not exist
	return ThreadLocalRandom.current().nextBoolean()
}

A simple solution could be to add Companion objects, even empty, to every relevant class in the standard library.

What do you guys think ? Or am I missing something ?


#2

We’re going to address the problem with missing companion object for Boolean in Kotlin 1.1, here is the issue https://youtrack.jetbrains.com/issue/KT-7922.

However I’m not sure we have to introduce a companion for every class in the standard library. It looks like an overkill, if all what those companions are going to provide is to be a receiver for static-like extensions. Also there are a bunch of java classes which could benefit from having such extensions.

Maybe we should allow having companion extensions without requiring companion classes to exist at all?


#3

That would be ideal indeed. I assumed it was not possible.


#4

Along the same lines, would that be extendable to generics? For example:

val <T : Any?> T.TAG: String
  get() = (this as? Any)?.javaClass?.simpleName ?: "null"

So I could say something like Int.TAG


#5

@eygraber What do you expect should be referred as this inside such generic function when it’s called on Int type (and not an instance of that type)?


#6

@ilya.gorbunov I didn’t think about that. Perhaps KClass<T>, but it would need a new syntax. Something like:

val <T : Any?> T.Static.TAG: String
  get() = this.javaClass.simpleName

#7

Any update on where we are with being able to have companion extension functions even if the receiving class has no companion object?

I just wrote an “extension” for KClass called forName() that works correctly even if the name represents one of the Kotlin primitive classes. However, since KClass has no companion object I ended up creating my own class called KClassCompanion and put a companion object on that. So, I have KClassCompanion.forName(), which will work and is somewhat intuitive.

However, this feels like a band-aid on a band-aid. There is no forName() equivalent and then when I try to write one it is ironically not pretty in a language whose stated goal is the opposite. The irony is that extension functions are called statically but it is not possible to use them statically. TBH, I somewhat question replacing simple static methods with a companion object because it appears to give rise to other issues and it is not clear to me what problem the companion object solves in the first place.

Or am I missing something?


#8

This feature is not on the roadmap for Kotlin 1.2; we haven’t done any planning for subsequent versions yet.


#9

Ok, thanks for the update!


#10

Why would you need this. It seems like you just using a class as a namespace for top-level function. It seems like this could just be top-level function scoped using the file.