Kotlin in Action Summary - Part 3
Tags: kotlin, android, programming
Published: 2022-09-01 12:16:23

This is part 3 of the series Kotlin in Action Summary. [Here is the link to part 2](https://dev.to/abolfazlimahdi/kotlin-in-action-summary-part-2-j68) which we talked about chapter 3 of the book with the title "Defining and Calling Functions". As mentioned before, it is highly recommended to read the book first and consider this series as a refresher. We do NOT cover all the materials in the book. Let's start with part 3, chapter 4 of the book: "Classes, Objects and Interfaces"!

# Contents
* [Interfaces](#header-1)
* [Open, Final and Abstract Modifiers](#header-2)
* [Visibility Modifiers](#header-3)
* [Inner and Nested Classes](#header-4)
* [Sealed Classes](#header-5)
* [Constructors and Properties](#header-6)
* [Universal Object Methods](#header-7)
* [Data Classes](#header-8)
* [Class Delegation](#header-9)
* [The `object` Keyword](#header-10)


## Interfaces <a name="header-1"></a>
###### pages 68, 69, 70
Kotlin's interfaces are similar to that of Java 8. They can contain abstract methods and implementation of non-abstract methods(like Java 8 default methods), but they cannot have any state!
This is how we declare and use interfaces in Kotlin:

```kotlin
interface Clickable {
    fun click()
    fun showOff() = println("Clickable showOff")
}

interface Focusable {
    fun setFocus(b: Boolean)
    fun showOff() = println("Focusable showOff")
}

class Button: Clickable, Focusable {
    override fun click() = println("button clicked")
    override fun setFocus(b: Boolean) = println("set focus")

    override fun showOff() {
        super<Focusable>.showOff()
        super<Clickable>.showOff()

    }
}
```
Here are some points to consider:
* In Kotlin, we use colon `:` instead of `implements` and `extends` keywords
* `override` is like the `@Override` annotation in Java, but it is mandatory to use in Kotlin.
* To provide implementation for a method in Kotlin, we do not need to use the `default` keyword. 
* If we implement two interfaces in a class that contain the same method signature, we must provide the implementation of that method in our class.
* To call the parent class's method, we need to use the `super` keyword in Kotlin. But to select a specific implementation we need to use `super` alongside with the `ClassName` inside angle brackets: `super<Clickable>.showOff()`

## Open, Final and Abstract Modifiers <a name="header-2"></a>
###### pages 70, 71, 72
In contrast to java, Kotlin classes are `final` by default. If we want to allow a class to be extended, we need to mark it with the `open` modifier. All properties and methods of that class are also `final`, so we have to use the `open` modifier for every one of them that we want to be overridden.

```kotlin
open class  RichButton : Clickable {
    // 1
    fun disable() {}
    
    // 2
    open fun animate() {}

    // 3
    override fun click() {}
}
```
* 1 -> `disable()` function is not _open_ (methods are _final_ by default), so it cannot be overridden
* 2 -> `animate()` function is _open_, so it can be overridden
* 3 -> `click()` function overrides an _open_ method, so it is _open_ itself and can be overridden

**NOTE:** If we override a member of a base class or interface, the overridden member is _open_ by default. To prevent it from being overridden, we should mark it with `final` modifier.

As in Java, Kotlin supports _abstract_ classes which cannot be instantiated. Why do we use _abstract_ classes? Sometimes we need a contract but do not want to provide implementation. We want the implementation to be provided by the subclasses. Abstract members of an abstract class are always open and do not require us to use `open` keyword:

```kotlin
abstract class Animated {
    // 1
    abstract fun animate()

    // 2
    open fun stopAnimating() {}

    // 3
    fun animateTwice() {}
}
```
* 1 -> `animate()` function is marked with `abstract` keyword, so it is open and do not need the `open` modifier
* 2 -> `stopAnimating()` function is marked with `open`, so it can be overridden
* 3 -> `animateTwice()` function is neither `abstract` nor `open`, so it cannot be overridden by subclasses.

**NOTE:** A member in an interface is always _open_; we cannot declare it to as _final_. It's _abstract_ if it has no body, but the keyword is not required.

## Visibility Modifiers <a name="header-3"></a>
###### pages 73, 74
Visibility modifiers help us to control access to declarations in our code base. Why should we do so? Because by enforcing encapsulation, we are sure that other classes do not depend on the implementation of our class, but rather on the abstraction. We can freely change the implementation and do not break anything in the client code!

Visibility modifiers in Kotlin are similar to those in Java. We have `public`, `private`, and `protected` with some differences. One difference is that, a class with no modifier is public by default and Kotlin does not support package-private modifier.
Why Kotlin does not have package-private modifier? Because they have replaced it with something better: we can use `internal` to declare a class to be _visible inside a module_.
What is a module? A _module_ is a set of Kotlin files compiled together. It might be IntelliJ IDEA module, Gradle or Maven project.
What is the advantage? It provides real encapsulation for the implementation details of our module. 

Another difference is that Kotlin allows the use of `private` visibility for top-level declarations, including classes, functions and properties. These are visible only in the file where they are declared.

To list the difference in visibility between Java and Kotlin:
1. Kotlin default visibility is `public`
2. Kotlin does NOT have package-private visibility
3. Kotlin supports module private visibility with `internal` keyword.
4. Kotlin supports private visibility for top-level declarations meaning visible inside the file.
5. `protected` modifier in Kotlin is just visible to the class itself or its subclasses, but in Java, it is also visible to classes in the same package!
6. Unlike Java, an outer class doesn't see `private` members of its inner (or nested) classes in Kotlin
7. Kotlin forbids us to reference less visible types from more visible members(e.g. referencing a `private` class from a `public` function) because it will expose the less visible type!

```kotlin
// 1
fun TalkativeButton.giveSpeech() {
    // 2
    yell()
    
    // 3
    whisper()
}
```

* 1 -> 
* 2 -> 
* 3 -> 

## Inner and Nested Classes <a name="header-4"></a>
###### pages 75, 76,
As in Java, you can declare a class inside another class in Kotlin. Difference? Unlike Java, the Kotlin inner class does not have access to the outer class instance, unless we specify so.

A nested class in Kotlin is the same as a `static` nested class in Java. To turn a nested class to an inner class (so the inner class has a reference to the outer class), we have to mark it with `inner` modifier.

![Nested class vs Inner class](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wyqlgqm39xce6sp0ow76.png)

How do we reference an instance of an outer class inside the inner class? We use `this@OuterClassName` syntax as in the following example:

```kotlin
class Outer {
    inner class Inner {
        fun getOuterReference(): Outer = this@Outer
    }
}
```
In Java, we use `OuterClassName.this` syntax to refer to the outer class instance.

## Sealed Classes <a name="header-5"></a>
###### pages 77, 78
On the first glance `sealed` classes are similar to `enums`. The difference is quite obvious — `enums` are a group of related constants, `sealed` classes are a group of related classes with different states. The other difference is that, `enum` constant is available only in one instance, whereas `sealed` classes can have multiple instances with different values.

We use `sealed` classes when we want to impose restriction on the number of options and values to a super class. What would be the benefit? First, we don't have to provide an `else` branch in `when` expressions. Second, when we add another subclass to the super class, we get a compile time error if we don't cover that subclass in the `when` expressions that we have written.
Let's see an example:

```kotlin
interface Result
class Success(val data: Any) : Result
class Error(val error: Exception) : Result

fun result(result: Result) : Any =
    when (result) {
        is Success -> result.data
        is Error -> result.error
        else -> throw java.lang.IllegalArgumentException("Unknown Expression")
    }
```
In the sample above, there are some problems. First problem is that we always have to provide an else branch for every when expression we write for `Result` interface. Also, if we decide to add another type to the subtypes of the `Result`, say `NetworkError`, then we will face an `IllegalArgumentException` at runtime.

To resolve these issues, we use sealed classes. When we use sealed classes and handle all the subclasses in a `when` expression, we don't have to provide the else branch. If we add another subclass and forget to handle that new subclass in a `when` expression, we'll get a compile time error. Let's see the above example converted to a sealed class:

```kotlin
// 1
sealed class Result<out T> {
    // 2
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val error: Exception) : Result<Nothing>()
}

fun <T> result(result: Result<T>) : Any? =
    // 3
    when (result) {
        is Result.Success<T> -> result.data
        is Result.Error -> result.error
    }
```
* 1 -> `sealed` classes are open by default (because they are implicitly `abstract`), we don't have to provide the `open` modifier
* 2 -> we are able to subclass `sealed` classes just inside it or in the same file it is declared in 
* 3 -> when we use a `sealed` class inside a `when` expression and we cover all possible cases, we don't have to provide the `else` branch

**NOTE:** Under the hood, the `sealed` class has a private constructor which can be called only inside the class.

To list all the characteristics of `sealed` classes:
* They are implicitly abstract
* Subclasses must be declared inside itself or in the same file as it is in
* They ease the pain of providing else branches when we cover all the instances
* If we add another instance and we forget to cover that instance inside a `when` expression, we will get a compile time error


## Constructors and Properties <a name="header-6"></a>
###### pages 79, 80, 81, 82, 83, 84, 85, 86

### Primary Constructors
###### pages 79, 80, 81
You can read about Kotlin classes and constructors at [Kotlin Official site](https://kotlinlang.org/docs/classes.html).

Kotlin, just like Java, allows us to declare more than one constructor. However, Kotlin makes distinction between a primary constructor and secondary ones. 

```kotlin
class User(val name: String)
```
The primary constructor is declared after the class name, outside the class body. We can use the `constructor` keyword, or omit that if we don't have annotations or visibility modifiers. The primary constructor roles are:
1. specifying constructor parameters
2. defining properties that are initialized by constructor parameters

If we want to write the equivalent Java way of the code above, it would look like this:

```kotlin
// 1
class User constructor(
    // 2
    _name: String
) {
    val name: String

    // 3
    init {
        name = _name
    }
}
```
In the code snippet above we have two new keywords:

* 1 -> `constructor`: begins the declaration of a constructor in Kotlin
* 2 -> `init`: introduces an _initializer block_
* 3 -> `underscore`: the underscore in constructor parameter is used to distinguish the parameter name from the property name. We could have used `this.name = name` instead.

What is an _initializer block_?
An _initializer block_ contains code that's executed when the class is created and intended to be used together with primary constructors. 
Why do we need _initializer blocks_? Because the primary constructors are concise in Kotlin and cannot contain logic, we need initializer blocks.

**NOTE:** We can have more than one _initializer block_ in a class. Initializer blocks are executed in the same order as they appear in the code.

In the code snippet above, there can be two modifications:
* we can omit the `constructor` keyword if there are not visibility modifiers or annotations on primary constructor
* we can omit the initializer block and assign the property to to parameter directly.

```kotlin
class User(_name: String) {
    // 1
    val name = _name
}
```
* 1 -> This is called _property initialization_

Kotlin has an even more concise syntax for declaring properties and initializing them from the primary constructor. These properties can be declared as immutable (`val`) or mutable (`var`).

```kotlin
class User(val name: String)
```

As with functions, we can declare constructors with default values in Kotlin:
```kotlin
class User(val name: String = "John Doe")
```
**NOTE:** If all constructor parameters have default values, the compiler generates an additional constructor without parameters that uses the default values. It does so to make it easier to use Kotlin with libraries that instantiate classes without parameters.

If we extend another class, our primary constructor must initialize the super-class:

```kotlin
// 1
open class User(val name: String) {
    
}

// 2
class TwitterUser(username: String) : User(username) {
    
}
```
* 1 -> mark the super-class `open` to be able to extend it
* 2 -> `TwitterUser` must call its super-class constructor

Just like Java, if we don't provide any constructors, a no-arg constructor is generated for the class. And if we extend this class, we still need to call its constructor:

```kotlin
// 1
open class User

// 2
class InstagramUser : User() {
    
}
```
* 1 -> We did not declare any constructor for the `User`, but the compiler generates a no-arg constructor for the class
* 2 -> Although `User` does not have any declared constructor or parameters, we still need to call its generated constructor!

**NOTE:** Be aware of the difference between extending a class and implementing an interface in Kotlin. Because interfaces don't have any constructors, we don't put _parentheses_ after their name when implementing them!

**NOTE:** To make sure that a class cannot be instantiated, we should make the primary constructor `private`:

```kotlin
class User private constructor() {
    
}
```

### Secondary Constructors
###### pages 81, 82, 83
Because Kotlin has default values for constructor parameters, secondary constructors are not used as widely as they are used in Java. 
We declare secondary constructors (like primary constructors) with the `constructor` keyword.
Let's take a look at an example from the Android world:

```kotlin
open class View {
    constructor(ctx: Context) {
        
    }
    constructor(ctx: Context, attr: AttributeSet) {
        
    }
}

class TextView : View {
    // 1
    constructor(ctx: Context) : super(ctx) {
        
    }
    
    constructor(ctx: Context, attr: AttributeSet) : super(ctx, attr) {
        
    }
}
```
* 1 -> if we extend a super-class and declare secondary constructors, we need to call the super class constructor in every constructor that we declare by using the `super` keyword (the exception is when we call another constructor of our class)

Just as in Java, we can call another constructor of our class using the `this` keyword:

```kotlin
class TextView : View {
    val myStyle =     // some code to instantiate myStyle 
    
    constructor(ctx: Context, attr: AttributeSet) : super(ctx, attr) {

    }
    
    // 1
    constructor(ctx: Context) : this(ctx, myStyle) {

    }
}
```
* 1 -> we use `this` keyword to call another constructor of our class

### Properties in Interfaces
###### pages 83, 84
Kotlin interfaces can contain abstract properties. 

```kotlin
interface User {
    // 1
    val name: String
}
```
* 1 -> The interface does not have a state because of this property because it does not specify whether it is a field or just a getter. It just means that classes that implement the interface need to provide a way to obtain the value of `name`. Pay attention that all classes are overriding the `name` property.

```kotlin
// Primary constructor property
class PrivateUser(override val name: String) : User
 
// Custom getter -> it does not have a backing field
class SubscribingUser(val email: String) : User {

    override val name: String
        get() = email.substringBefore('@')
}

// Property initializer
class FacebookUser(val accountId: Int) : User {
    override val name = getFacebookName(accountId)

    private fun getFacebookName(accountId: Int): String {
        //code to get the facebook name
    }
}
```

### Accessing Backing Fields
#### page 85
Let's see how we can access a backing field from the accessors. To do so, we use the `field` identifier in the body of a setter.

```kotlin
class User7(val name: String) {
    var address: String = "unspecified"
        // 1
        set(value) {
            // 2
            println(
                """
            address changed for $name: 
            $field -> $value
            """.trimIndent()
            )
            // 3
            field = value
        }
    get() {
        // 2
        return "$name address: $field"
    }
}
```

* 1 -> We define a setter by writing a `set` function under the property (the property must be mutable (`var`))
* 2 -> We can access the property backing field by the `field` keyword.
* 3 -> We change the value of the property

**NOTE:** If we provide custom accessors for a property and do not use the `field` keyword, the compiler won't generate a backing field for that property (for getter in `val` property and for both accessors in `var` property).

```kotlin
class User(val name: String) {
    // 1
    var address: String = "unspecified"
        set(value) {
            println(
                "address for $name: $value"
            )
            
        }
    get() {
        return "$name address: "
    }
}
```
If we write such a code, it won't compile with the error _Initializer is not allowed here because this property has no backing field_. Why? Because we did not use the `field` keyword in neither the setter nor the getter. 

### Changing Accessor Visibility
#### page 86
The accessor's visibility is the same as the property's visibility. We can change the accessor's visibility by putting a visibility modifier before the `get` or `set` keyword.

```kotlin
class User(val name: String) {
    // 1
    var id: Int = 0
        // 2
        private set(value) {
            field = getAutoGeneratedId()
        }
        

    private fun getAutoGeneratedId(): Int {
        // code to get an auto generated id
    }
}
```
* 1 -> the property's visibility is public and can be accessed outside the class
* 2 -> we limit the setter's visibility to the class because we do not want other classes to set this property

**NOTE:**  Accessors cannot be more visible than the property itself. Meaning that if the property is `protected`, the accessors can be `private` but cannot be `public`!

## Universal Object Methods   <a name="header-7"></a>
###### pages 87, 88, 89

We use some classes specifically to hold data. These classes usually need to override some methods like `toString()`, `equals()`, and `hashCode()`.  Let's see how we should implement them in Kotlin.
First, we declare a `Person` class. 

```kotlin
class Person(
    val name: String,
    val phoneNumber: String,
    val address: String
)
```
#### toString()
`toString()` method is used primarily for debugging and logging. It should be overridden in almost every class to make the debugging easier. If we do not override the `toString()` method, when we print an object, the result looks like `Person@23fc625e`

```kotlin
class Person(
    val name: String,
    val phoneNumber: String,
    val address: String
) {
    override fun toString(): String {
        return "Person(name=$name, phone number=$phoneNumber, address=$address"
    }
}
```
#### equals()
`equals()` method is used to check whether two objects' values are equal, not the references!

```kotlin
class Person(
    val name: String,
    val phoneNumber: String,
    val address: String
) {
    override fun toString(): String {
        return "Person(name=$name, phone number=$phoneNumber, address=$address"
    }

    override fun equals(other: Any?): Boolean {
        if (other == null || other !is Person)
            return false
        return name == other.name &&
                phoneNumber == other.phoneNumber &&
                address == other.address
    }
}
```
#### hashCode()
The `hashCode()` method should be always overridden together with the `equals()` method! If two objects are equal, they must have the same hash code.

```kotlin
class Person(
    val name: String,
    val phoneNumber: String,
    val address: String
) {
    override fun toString(): String {
        return "Person(name=$name, phone number=$phoneNumber, address=$address"
    }

    override fun equals(other: Any?): Boolean {
        if (other == null || other !is Person) 
            return false
        return name == other.name &&
                phoneNumber == other.phoneNumber &&
                address == other.address
    }
    
    override fun hashCode(): Int {
        return name.hashCode() + 
                phoneNumber.hashCode() + 
                address.hashCode()
    }

}
```

**NOTE:** Why the `hashCode()` method should be always overridden together with the `equals()` method? Because some clients (like `HashSet`) first use the `hashCode()` method to check for equality and if the hash codes are equal, then they check the `equals()` method!


## Data Classes   <a name="header-8"></a>
###### pages 89, 90, 91
Kotlin has made it easier for us to declare classes to hold data. We just mark that class with the `data` modifier and the Kotlin compiler would generate the previously mentioned methods for us! The compiler will generate `toString()`, `equals()`, `hashCode()`, (also `copy()`, and `componentN()`) functions from the properties declared in the primary constructor.
```kotlin
data class Person(
    val name: String,
    val phoneNumber: String,
    val address: String
)
```
The `Person` class above is somehow equal to the `Person` class we declared before this (with `toString()`, `equals()`, `hashCode()` methods overridden).

Data classes must fulfill the following requirements:
1. The primary constructor needs to have at least one parameter.
2. All primary constructor parameters need to be marked as val or var.
3. Data classes cannot be abstract, open, sealed, or inner.


**NOTE:** As we mentioned earlier, the compiler just takes into account the properties in the primary constructor. In other words, we can declare properties in the class body to exclude it from generated implementations(like `toString()` and `hashCode()`).

#### `copy()` Method
It's strongly recommended that we use read-only (`val`) properties to make the instances of data classes _immutable_. This is mandatory if we want to use such instances as keys in a `HashMap` or a similar container, because otherwise the container could get into an invalid state if the object used as a key is modified after it was added to the container.


----

## Class Delegation   <a name="header-9"></a>
Sometimes we need to change the behavior of a class, but we cannot extend that class (either our class has another parent class, or the class we want to extend is not `open`). In this situation, we can use the decorator pattern:

* We implement the same `interface` that the class we want to extend is implementing
* We declare a property of type of the class we want to extend
* We forward the requests that we don't want to change to that property
* If we want to change the behavior of a method, we will `override` that method in our class
Let's see this pattern in practice:
```kotlin
class DelegatingCollection<T> : Collection<T> {

    private val innerList = arrayListOf<T>()
    
    override val size: Int get() = innerList.size

    override fun isEmpty() = innerList.isEmpty()

    override fun iterator() = innerList.iterator()

    override fun containsAll(elements: Collection<T>) = innerList.containsAll(elements)

    override fun contains(element: T) = innerList.contains(element)

}
```
Here, we have used the _decorator pattern_ as we use it in Java. We forward every call to the `innerList` variable of type `ArrayList`. If we want to change the behavior of the method `isEmpty()`, we can easily do so be defining our own implementation.

Fortunately, Kotlin has provided a first-class support for delegation. To use this feature:
* We extend the same interface as our class we want to extend
* We declare a property of the class we want to extend
* We use the `by` keyword after the interface implementation.
```kotlin
class DelegatingClass<T>(
    val innerList: Collection<T> = ArrayList<T>()
) : Collection<T> by innerList 
``` 
This is just the same as the implementation before with much less boilerplate code! We have used the `by` keyword to delegate the requests to the object specified(`innerList` here)!



## The `object` Keyword <a name="header-10"></a>
###### pages 93, 94, 95, 96, 97, 98, 99, 100, 101
The `object` keyword in Kotlin is used to _define a class and create an instance of that class at the same time_.

### Object Declaration
###### pages 93, 94, 95
Singleton design pattern is used fairly common in object-oriented design systems. Kotlin provides _object declaration_ which combines the _class declaration_ and a declaration of a _single instance_ of that class.
```kotlin
object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
        // ...
    }

    val allDataProviders: Collection<DataProvider>
        get() = // ...
}
```
Object declarations are created with `object` keyword. An object declaration defines a class and a variable of that class in a single statement.

**NOTE:** If we pay attention to its name (_object declaration_), we understand its purpose. We declare an object, and to declare an object, we must create an instance of that object. With object declarations, we combine the two steps.

An _object declaration_ is just like a normal class with one difference: it does not allow constructors to be declared in it. Objects of _object declarations_ are created immediately at the point of definition, not by calling their constructors.

**NOTE:** _Object declaration_, like a variable declaration, is not an expression and cannot be used on the right-hand side of an assignment statement!

_Object declarations_ allow us to call their methods and access their properties by using the class name and the . character:

```kotlin
val numberOfDataProviders = DataProviderManager.allDataProviders.size

DataProviderManager.registerDataProvider(/*...*/)
```
_Object declarations_ can inherit from classes and interfaces. This is often useful when the framework requires us to implement an interface, but our implementation does not contain any state! The `Comparator` interface is a great example for this. A `Comparator` implementation receives two objects and returns an integer indicating which of the two objects is greater! Comparators never store any data, so we usually need a single `Comparator` instance for a particular way of comparing objects. This is a perfect use for object declaration!

```kotlin
data class Person(val name: String, val age: Int)

object AgeComparator : Comparator<Person> {
    override fun compare(p1: Person, p2: Person): Int {
        return p1.age - p2.age
    }
}
```
We can use singleton objects in any context where an ordinary object can be used.


We can also declare objects in a class. Such objects also have just a single instance; they don't have a separate instance per instance of the containing class. Take the `Person` class as an example. Isn't it more logical to put different `Comparator` implementations inside the class itself for further use?

```kotlin
data class Person(val name: String, val age: Int) {
    
    object AgeComparator : Comparator<Person> {
        override fun compare(p1: Person, p2: Person): Int {
            return p1.age - p2.age
        }
    }

    object NameComparator : Comparator<Person> {
        override fun compare(p1: Person, p2: Person): Int {
            return p1.name.compareTo(p2.name)
        }
    }
}
```

To refer to the instance of the singleton object in Java which is created by the _object declaration_, we should use the `INSTANCE` static field:

```java
AgeComparator.INSTANCE.compare(person1, person2);
```

#### Companion Objects
###### pages 96, 97, 98, 99, 100
Kotlin does not have the `static` keyword which exists in Java. Most of the time, our needs for `static` members and methods is satisfied with top-level member and functions in Kotlin. However, we cannot access `private` members of the class. So, if we need to write a function that can be called without an instance of the class, but has access to the private members of the class, we can use the `object declaration` inside that class.

**NOTE:** Please be aware that `companion object` (just like static methods) cannot access instance members of the class. To do so, we must provide an instance of the class for the companion object:

```kotlin
class Person {
    
    private lateinit var name: String
    
    object Print {
        fun printName1(person: Person) {
            println(person.name)
        }
        
        fun printName2() {
            val person = Person()
            println(person.name)
        }
    }
}
```
If we mark the `object declaration` with the keyword `companion`, we can access the methods and properties inside that object declaration directly through the name of the containing class (without specifying the object name).

For example, to call the methods in the above example, we use this syntax:
```kotlin
Person.Print.printName1(Person())
Person.Print.printName2()
```

Now, if we omit `Print` (the object declaration name) and put the `companion` keyword before `object`, we can use the methods like static methods in Java:

```kotlin
class Person {

    private lateinit var name: String

    companion object {
        fun printName1(person: Person) {
            println(person.name)
        }

        fun printName2() {
            val person = Person()
            println(person.name)
        }
    }
}
```
To use the methods above, we use this syntax:
```kotlin
Person.printName1(personInstance)
Person.printName2()
```

Note that we do not use any object name (`Print` in previous example) to call the methods inside `companion object`.

One of the most important use-cases of `companion object` is to implement the _factory pattern_. Why? Because companion objects have access to the private members of the class, including the constructors.

```kotlin
class Person private constructor(val name: String, val role: Role){
    
    companion object {
        fun newManager(name: String) = 
            Person(name, Role.MANAGER)
        
        fun newEmployee(name: String) =
            Person(name, Role.EMPLOYEE)
    }
    
    enum class Role {
        MANAGER, EMPLOYEE
    }
}
```
Here, we have used factory methods to create instances of the `Person` object. To create instances of `Person`, we use the class name with the method from the companion object:

```kotlin
Person.newManager("Tom")
```
Factory methods are useful for several reasons:
* They can be named according to their purpose
* Can return subclasses depending on the method that we invoke
* We can also avoid creating new objects when it's not necessary.

The downside with using factory methods instead of constructors is that we cannot override them in subclasses!

##### Companion Objects Extension
We can define an extension function (just like normal extension functions) for companion objects. The only requirement is that the class should have at least one companion object. If it does not have any, we should define an empty one to extend it.
Suppose we want to add an extension function (say `setupFakeManager()`) to the `Person` class we declared earlier. Here is a sample code:

```kotlin
fun Person.Companion.setupFakeManager() : Person {
    return Person.newManager("FakeManager")
}
```

Because we had a companion object in the `Person` class, we just extended the companion object to have another function. Note the `Companion` keyword after the class name. By using the `Companion` keyword, we are indicating that we are extending the companion object!

#### Object Expressions
The third use-case of the `object` keyword is to declare _anonymous objects_. Anonymous objects are here to replace the Java's anonymous inner classes. For instance, we can use them to setup click listeners in Android:

```kotlin
button.setOnClickListener(object : View.OnClickListener {
    override fun onClick(view: View?) {
        // Do some work here
    }

})
```
As we see, the syntax is the same as the _object declaration_ but we have dropped the object name!

**NOTES:** Object expressions in Kotlin:
* can implement multiple interfaces or no interfaces(Java can just extend one class or implement one interface).
* can access the variables in the function where they are created.
* are useful when we want to override multiple methods in our anonymous object. Otherwise, we are better to use lambda expressions.
* if we need the instance of it, we can assign the expression to a variable.


This is the end of part 3 which was the summary of chapter 4 (a long one:-) ). There were other parts in chapter 4 that I did not cover here because I felt they are not as important and they would have made the article too long. Anyhow, if you found this article useful, please like it and share it with other fellow developers. If you have any questions or suggestions, please feel free to comment. Thanks for your time.