Companion Objects


#1

Hi,

Can someone please explain to me in details what is companion object! I have been following a course about Kotlin from A - Z and when the instructor reached the companion object I didn’t understand anything and I had to skip all lessons related to companion objects

Please don’t compare it to Java as I have no experience in java

Thanks.


#2

If you understand static, you don’t need to read the rest of my answer.
Everything in companion object are functionally equivalent to static methods/variables

A class is a blueprint for creating objects.
For example, let’s create a couple of carObjects:

class Car(val color: Color, var owner: String){
    fun drive() =TODO()

}

fun main(vararg args : String){
    val carObject1 = Car(Color.Red, "foo")
    val carObject2 = Car(Color.Blue, "bar")

}

when you use the keyword object, you say that you don’t need the blueprint, but immediately want the created object. You say this when you never need to have more than one object of that blueprint. An example would be settings for your program. You can make the object implement interfaces or extend a class.

a companion-object is a bit a combination of both worlds.
As you see in the car-class, there is a drive-method. This method belongs to the objects that you create.

carObject1.drive()  //you drove in carObject1
carObject2.drive()  //you drove in carObject2

But it is possible you want to have an object that every car shares. Because you don’t need a blueprint//class you use object. This object however belongs to the bluePrint car. Then you use a do called companion-object. In other words, an object that comes with the blueprint.

An example:

class Car{
    companion object{
          fun build() = Car()
    }

}

This is called as

Car.build()

The most important reason why I use this is to have shared variables or to create an dsl.


#3

A companion object is not a holder for static functions variables. It’s a singleton shared between a classes of the same type. If you going to use them like static function be cognizant of a few things.

A companion object does create a object so it takes up memory.

Also, Kotlin doesn’t have the static keyword because it’s recommended to use top-level functions instead. However, since top-level functions can’t access a private members in a class which a companion object allows you to do.


#4

First thing to learn and understand is Kotlin’s object class.

  object Foo {
    fun bar() = print("hello")
  }

This will not only declare a class named Foo that has a member function named bar. It will also create a Singleton instance of this class. To access that Singleton instance and it’s function, you write Foo.bar(). There is no way to create a second instance of this Foo class.

Now, companion objects are very similar to these object classes. The difference is that they are embedded within another class, and there is some syntactic sugar for companion objects.

You can access a companion object like this Car.Companion.build(), or use the shortcut syntax Car.build().


#5

Not sure if you are ok with previous response, but there’s one more without the word static which generally confuse beginners :

in a class, almost everything is referenced by an instance of that class. This means that if you want to call a method of a class, you need to call the method from an instance of the class.

class X {
  fun hello() = println("hello")
}

fun main(){
  X() //creating the instance
    .hello() // and calling the method from it
}

so I said ‘almost everything’ because class are (by default) defined in the class (and not in the instance):

class X{
  class ClassInX{
    fun hello() = println("hello")
  }
}

fun main(){
  X.ClassInX() //note we don't use an instance of X(X() is just X) to use ClassInX, just the class
    .hello()
}

so now… there is a special “type” of class which are called object : in kotlin, an object is a class, and also an instance of it: the only instance of a class is itself. this means you don’t need to instanciate the class, it is already instaciate (only once, when the class is loaded, so this instance is shared by all the application):

class X{
  object ObjectInX{
    fun hello() = println("hello")
  }
}

fun main(){
  X.ObjectInX //like a class Z is bound to x
    //// BUT it is already an instance : we can call the method directly without () in previous line
    .helloz()  
}

so now there is a “special object”: the companion object : the companion object is an object which is called Companion. But the biggest thing of a companion object is that the compiler will add for you the .Companion when this can be done:

class X{
  companion object {
    fun hello() = println("hello")
  }
}

fun main(){
  X.Companion.hello() // works exactly the same that ObjectInX
  //and now the magic : 
  X.hello() //the compiler will deduce you want to use X.Companion.hello()
}

so if you understand all this, I now invite you to try to understand the notion of “static” which is quite important I think (and present in a lot of languages).


#6

One should note also that in all examples above the Singleton instances can also contain data (i.e. properties). The properties will be stored in fields of the Singleton instance. Just like in regular instances.


#7

Thank you guys for your amazing replies.


#8

thank u very much!


#9

Companion object is akin to static methods. However, what’s really cool is that it’s an object which can extend from other objects and/or implement interfaces (with possible mixin methods). For example, I can have a Dao interface which mixes in methods such as findAll(), findById() etc. Then, you simply declare your companion object to implement the Dao interface and voila - finders are automatically attached to your bean.

For example, say you have the following entity:

data class Category(override var id: Long? = null, var name: String = "") : Entity<Long> {
    companion object : Dao<Category>
}

Then you can simply write:

val categories: List<Category> = Category.findAll()

Please see more at https://github.com/mvysny/vok-orm


#10

Good example. Thank u very much!


#11

This is more understable, thanks