Extension Objects

I’d love to able to extend a type with a named object. This would help a lot with types that I don’t control and don’t define a public companion object.

Example:

package com.whatever.name

class Name(val value: String)

package com.whatever.name.extensions

object Name.Comparator : Comparator<Name> {

    override fun compare(one: Name, other: Name): Name = TODO("whatever")
}

And then

import com.whatever.name.Name
import com.whatever.name.extensions.Name.Comparator

fun main() {
    
     val names = listOf("Second", "First").map(::Name)

     val sorted = names.sortWith(Name.Comparator)
}

EDIT 2: Okay so I misunderstood a bit. Let’s see if I can fix this:
I originally read your proposal as being able to extend a class with an object. But seeing your example, it looks like you really want to extend a class’s companion object with a property.

While you can already do this by val Name.Campanion.foobar: String = "foobar", if the class you’re extending doesn’t already have a companion object, you’re out of luck. Being able to extend a companion of a class that doesn’t have an explicit companion has been requested. The namespace solution is the most recently discussed.

You can see the video about that and other possible future Kotlin features here.


Original reply:

You can already do this using extension methods and properties:

Here’s how you could do it with an extension property:

// top-level declaration.
val Name.comparator = object : Comparator<Name> { /* ... */ }

Since a top-level object is basically the same as a global val anonymous object, you can use that for now. Or another way of saying it: The proposed “extension object” is just another conceptual version of an extension property, which already exists.

EDIT:
I moved the stuff about other proposals to a details here since it’s more of a side note:

related proposals

There are a few proposals that may be related:

One discussed direction is namespaces. You can see the video about that and other future Kotlin development here.
I’m not sure if the various proposals for type classes would apply to this use case or not but there may be some overlap. I suspect it would.

1 Like

No, you understood correctly the first time. I meant extending a class with one or more named objects.

Probably I’m the one to blame for the confusion :slight_smile:

Namespaces would work but it’d be great to be able to attach multiple ones vs 1 without a name.

I think part of the confusion comes from the example code that shows Name.Comparator (note capitalized class name). This is an example of extending the class Name’s companion class.

Saying “extending a class with one or more named objects” doesn’t fully explain it either since it sounds like you want to extend the class (the kind) which is just a normal extension property. Extending a class usually means adding functionality that could be used via an instance of that class.

Maybe the confusion is coming from the slightly misleading idea that object means “static” or has some global-ness or some inherent tie in to a class namespace?
Declaring an object as a top-level declaration does create a singleton. However, it may be helpful to think of this as a top-level anonymous object instead.

A companion object is a member of every instance of a class. It seems like you want the ‘camparator’ to be a a member of the companion, and you don’t want each instance of name to have a comparator.
If that were the case you’d have to say myName.comparator instead of `Name.comparator’.

The ‘object’ declaration has nothing to do with static. There’s nothing preventing a change that allows you to declare static extensions like you ask but it may not be the best fit conceptually.

Again, ‘object’ has nothing directly tying it to “static” (aka, member owned by every instance) by itself. If you want to call a shared available single instance of camparator using the capitalized type name, Name.comparator, then you want to extend the Name class’s companion object. Another way of saying it is: you want to add a property to the Name class’s namespace. Or a third way, more Java this time: you want a static camparator for the Name class.

Your request is already available for classes that have a companion object declared. But right now it’s impossible to extend a class that wasn’t already given a companion object. That’s the reason I suggested your request is the same as those asking to allow extension on companions for classes that don’t have an explicit companion object already declared. You may be able to find more discussion on this topic searching with the companion wording as well.

1 Like