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?

9 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