Kotlin Object Vs Companion Object
Tags: kotlin, android, java
Published: 2020-03-09 00:52:07

Recently I came across a question during a code-review. It was in the context of a PR where kotlin `class` and a bunch of functions inside a `companion object {}` annotated as `@JvmStatic` for Java interoperability were used. The feedback was "why we can't convert the `class` into an `object` and get rid of the `companion object {}`?".This raised the question, `"what is the benefit with that?"`. Some explanation was done, but I wasn't completely satisfied with the explanation given (by me :)). So, decided to do a bit reading and document the differences, and use-cases for my future reference and for someone who will stumble upon similar question.

#### Object
`Object` in kotlin is a way of implementing `Singletons`. We all have come across the need of `Singleton` pattern in our career for various use-cases. Well, in kotlin this has been made very straight forward. 
e.g.
```kotlin
object MyObject {
  // further implementation
  fun printHello() {
    println("Hello World!")
  }
}
```
This implementation is also called `object declaration`. Object declarations are thread-safe and are `lazy initialized`, i.e. objects are initialized when they are accessed for the first time.

#### Companion Object
If we want some implementation to be a `class` but still want to expose some behavior as `static` behavior, `companion object` come to the play. These are `object declarations` inside a class. These companion objects are initialized when the containing class is resolved, similar to `static` methods and variables in java world.
e.g.
```kotlin
class MyClass {

  // some implementations
  
  companion object {
    val SOME_STATIC_VARIABLE = "some_static_variable"
    fun someStaticFunction() {
      // static function implementation
    }
  }
}
```

####Summary
Given the above explanation, the use-case completely depends on the problem we are trying to solve. If we need to provide the `Singleton` behavior, then we are better off with `Objects`, else if we just want to add some `static essence` to our classes, we can use `Companion objects`.


#### Bonus - Accessing Objects & Companions from Java
`@JvmField`, `lateinit`, `const`, `@JvmStatic` are handy when it comes to accessing field properties or functions defined in `objects` or `companion objects`.
e.g. our `object` can be something like below
```kotlin
object MyObject {

  @JvmStatic
  fun printStaticHello() {
    println("Static Hello World!")
  }

  fun printNonStaticHello() {
    println("Non-Static Hello World!")
  }
}
```
From `Java` world, we can access those functions as:
```
MyObject.printStaticHello() OR
MyObject.INSTANCE.printNonStaticHello() - this uses the singleton instance
```

e.g. accessing `companion object`
```kotlin
class MyClass {
  
  companion object {
    @JvmStatic
    fun printStaticHello() {
      println("Static Hello World!")
    }

    fun printNonStaticHello() {
      println("Non-Static Hello World!")
    }
  }
}
```
From `Java` world, we can access those as:
```
MyClass.printStaticHello()
MyClass.Companion.printStaticHello()
MyClass.Companion.printNonStaticHello()
```

Thank you for reading.
Note: Further reading and references, [here](https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations) & [here](https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html#static-fields)