Companion object and function extension

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 ?

3 Likes

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?

10 Likes

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

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

@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)?

@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

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?

1 Like

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

Ok, thanks for the update!

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.

Hi, everyone.

I just bumped into the same problem here…

I created something like this for serialization in a module:

internal fun Long.Companion.fromByteArray(byteArray: ByteArray): Long {
    val buffer = ByteBuffer.wrap(byteArray)
    return buffer.getLong(0)
}

Now, I need to do the same thing for LocalDate (which has no Companion), and it doesn’t work. As a workaround, I created the extension function to the KClass, but it’s looks ugly to rely on reflection API to achieve that.

Any updates on this topic?

1 Like

Any update here? Being able to create extension functions at this level without companion object would be great.

On my side I work on Toothpick/KTP, a DI framework. By having this feature, the runtime performance and complexity of the generated code would improve drastically.

1 Like

This would be a great feature, making it comfortable to avoid namespace pollution.
As it stands now, we cannot rely on the existence of companion classes.

Any updates on this?

@ilya.gorbunov Are extension functions creation ability for JVM standard library classes planned for any future release?

Has an issue already been created for that?
I’d like to a add a factory method for java.time.Instant but there isn’t a Companion object too.

Edit: Found issue and related question at Stackoverflow