26

The documentation for companion objects has the following example

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}

Here Factory is the name of the companion object. It then goes on to say:

The name of the companion object can be omitted, in which case the name Companion will be used:

However there is no example that I can see that uses the name of the companion object.

Since you can only have one companion object per class (otherwise you get a Only one companion object is allowed per class error) the name feels like some pretty useless syntactic sugar to me.

What can the name of the companion object actually be used for? Why would one bother to use any name for it?

Grzegorz Piwowarek
  • 13,172
  • 8
  • 62
  • 93
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
  • 1
    check this : https://stackoverflow.com/questions/38381748/why-do-we-use-companion-object-as-a-kind-of-replacement-for-java-static-fields – Maddy Aug 24 '17 at 05:35
  • 2
    @Maddy that seems to address why a companion object is called a companion object, not why you might bother to specify a name for your companion object. – Michael Anderson Aug 24 '17 at 05:57

4 Answers4

15

You can use the name of the companion like:

MyClass.create()           // not via companion name
MyClass.Companion.create() // via default companion name
MyClass.Factory.create()   // via companion name

The name is maybe not that important for Kotlin, because you can just access the method without knowing that there is a companion object (line one above). It is more like a personal style, if you want to make the access to such functions more explicit.

But for java interop it makes a difference, because you have to access the function via the companion name:

    MyClass.Factory.create();   // with named companion
    MyClass.Companion.create(); // with unnamed comanion
guenhter
  • 11,255
  • 3
  • 35
  • 66
  • So it changes the way you call the java functions slightly - but there are existing ways to change how a class gets named when exposed to the JVM in particular `@JvmName` - why not use those? – Michael Anderson Aug 24 '17 at 05:59
  • You can use `@JvmName' for functions, but not for the name of the `companion-object` itself. – guenhter Aug 24 '17 at 06:19
  • 1
    @MichaelAnderson also, `@JvmName` only works on the JVM, but Kotlin also targets JavaScript and native – Lovis Aug 25 '17 at 12:42
  • 1
    AFAIK, when importing a companion object's feature, or referring to it as a method literal ([callable reference](https://kotlinlang.org/docs/reference/lambdas.html#instantiating-a-function-type)), you need to specify the companion name. – Rafael Chaves Feb 03 '21 at 20:30
5

Well, companion objects in Kotlin are not just syntactic sugar. They are actually a type. They are able to do much more thing, and need not to be see as just replacement of static.

You can actually extend class or implement an interface. See an example below.

open class Super {
    open fun sayHello() {
        println("Hello")
    }
}

class Some {
    companion object Child : Super() {
        override fun sayHello() {
            super.sayHello()
            println("Hello from companion object")
        }
    }
}

fun main() {
    Some.Child.sayHello()
}
Hardik Trivedi
  • 5,677
  • 5
  • 31
  • 51
2

If you do not use an explicit name, the companions name is Companion, thus it can be omitted, like you already quoted.

Sometimes you may want to have an explicit name in your calls, which would be MyClass.Factory.create() in your example. For namespace reasons maybe.

I don't see a many reasons to name a companion object, either. Except if you care about Java interop with your Kotlin code. Then, you need to explicitly write the companions name.

Another reason you might care about the name is, when you define an extension function on it:

  fun MyClass.Companion.ext() = "myext"

In this case, it can be clearer when it has a name like Factory, on which specific factory methods are added via extension.

s1m0nw1
  • 76,759
  • 17
  • 167
  • 196
  • 1
    I can see this as being useful if you can have more than one companion object - so that you could group the factory functions into one, the utility functions into another. Can you do that? Otherwise it feels rather pointless. – Michael Anderson Aug 24 '17 at 05:52
  • In answer to my own question there - you can only have one companion object per class. You get a `Only one companion object is allowed per class` error otherwise. – Michael Anderson Aug 24 '17 at 05:53
  • 2
    The reasons I see: Java interop and extension function definition – s1m0nw1 Aug 24 '17 at 06:24
  • Yes. The main purpose of having a name for companion object is to define extension functions that can be called on the class itself instead of instance of a class. – BakaWaii Aug 24 '17 at 06:43
  • You can still use the the extension function on the companion object when using the unnamed version. The default name of Companion works fine there. So IMO its still not really a reason for the user to be able to name it. – Michael Anderson Aug 24 '17 at 06:59
  • Well then there's no reason for you to name it ;-) – s1m0nw1 Aug 24 '17 at 07:00
  • @Michael Anderson Oh, then I misunderstand your question. Since I see you are asking "What can the name of the companion object actually be used for?" and `Companion` is used as a name implicitly. – BakaWaii Aug 24 '17 at 08:10
1

However there is no example that I can see that uses the name of the companion object.

class Person(val name: String) { companion object Loader {
fun fromJSON(jsonText: String): Person = ... }
}
>>> person = Person.Loader.fromJSON("{name: 'Dmitry'}") >>> person.name
Dmitry
>>> person2 = Person.fromJSON("{name: 'Brent'}") >>> person2.name
Brent
TooCool
  • 10,598
  • 15
  • 60
  • 85