The Companion Objects to handle Java Static in Kotlin

- Andrés Cruz

En español
The Companion Objects to handle Java Static in Kotlin

In this post we will continue our Kotlin tutorials detailing features that make it a modern language for application development; its simple, straightforward, direct and concise coding helps a lot in timing and the general understanding of the code; We will see a concise code example below with the use of complementary objects that has been the way in which Kotlin works with Java statics; another approach that you can use is the famous singleton classes that are used a lot in applications, such as Android, which is our special interest.

Example of the operation of Companion Objects in Kotlin

To use the Companion Objects in Kotlin, they must be declared within the instance of a class as follows:

class Persona {

   companion object Raza {

       // clasificacion persona
       val edades: IntArray = intArrayOf(0, 2, 30, 60)
       var razas =
               arrayOf("Europeo", "Asiatico", "Latino", "Arabe", "Africano", "Americano", "Canadiense")
       var clasificacion = "Clasificación personas"

       init {
           println("Inicializando el companion")
       }

       fun enAmerica(): Array<String> {
           return arrayOf(razas[2], razas[5], razas[6])
       }

       fun adultoMayor(): Int {
           return edades[3]
       }

       fun printClasificacion() {
           println(clasificacion)
       }
   }
}

In the first instance, it seems to use a more complex structure, since we are nesting elements, in this case our class inside a Companion Object, and it is true, but it gains in readability, since it is very common that we want to define an important block as static, and we don't have to be placing the word static all the time to define multiple functions, or parameters as we did in Java, with the aggregation that we do with the Companion Object it is more than enough to encompass all our methods and static properties at once; in Java we would have to do the following.

public static final String KEY = "key";

Now, if we have several structures and variables that we want to be static, then everything becomes quite complicated, because we have to be placing static all the time, and if we also have methods and attributes that are not static, in the end what we have is a good mix of various things; something that does not happen with Kotlin when including in a block of code the properties and functions that we want to be static through the Companion Objects.

In the previous example, we can see that we declare our Companion Object within the Person class, as a fundamental principle, to create and later use a Companion Object, it must be declared within a class as we did before, that we declare the Companion Object called Race within the parent class Person.

Accessing the methods of the Companion Object

With the Companion Object already declared, we create some properties such as ages and races that are Arrays which we create custom methods for each scope in this example, that is, we create as an example an enAmerica() method that returns an Array with the native races of the American continent, which would be those of Latinos, Americans (North America) and Canadians.

We do something similar with the ages, which we create a method called adultOlder() that returns the age in which it is considered that from the same, the person is an older adult.

We also create a text through a variable called classification that returns its value through the printClassification method.

Finally, we can use a constructor defined as init if necessary.

Variations on the Companion Object structure to handle static

We can omit the name of the Companion Object from the declaration, remaining as follows:

class Persona {

   companion object {

       // clasificacion persona
       val edades: IntArray = intArrayOf(0, 2, 30, 60)
       var razas =
               arrayOf("Europeo", "Asiatico", "Latino", "Arabe", "Africano", "Americano", "Canadiense")
       var clasificacion = "Clasificación personas"

/*Demas metodos*/

}

In order to use methods or properties of the Companion Object we use the following scheme; taking the previous code as an example, we have:

println(Persona.enAmerica()[0]) println(Persona.printClasificacion()) println(Persona.adultoMayor()) }

Accessing the properties of the Companion Object

To reference the methods we saw previously; Of course, we can directly reference the properties as we have done in previous posts, and this is excellent, since we don't have to create the famous get and set methods for each property of our object; declaring the property and its type is a necessary and sufficient condition:

Persona.edades
Persona.razas
Persona.clasificacion

As we can see, we must use the name of the mother class followed by the method or property defined within the Companion Object, it is the same approach as the one used in Java when referencing a method or property of a static class in Java; that is, we first reference the name of the class and then reference the method or property of the Companion Object without the need to create an object of the class.

Companion Object parent class methods

We can define the structure of our class as we want, taking as reference the structure that we saw in a previous post:

Clases en Kotlin: clases vacías, constructores y propiedades

We have that our code would look like this:

class Persona {

   var nombre: String = ""
   var apellido: String = ""
   var edad: Int = 0

   init {
       this.nombre = nombre
       this.apellido = apellido
       this.edad = edad
   }

   companion object Raza {

       // clasificacion persona
       val edades: IntArray = intArrayOf(0, 2, 30, 60)
       var razas =
               arrayOf("Europeo", "Asiatico", "Latino", "Arabe", "Africano", "Americano", "Canadiense")
       var clasificacion = "Clasificación personas"

       init {
           println("Inicializando el companion")
       }

       fun enAmerica(): Array<String> {
           return arrayOf(razas[2], razas[5], razas[6])
       }

       fun adultoMayor(): Int {
           return edades[3]
       }

       fun printClasificacion() {
           println(clasificacion)
       }
   }
}

Creating a Singleton class

All of the examples we saw above are Singleton classes, which by definition are classes with a single instance throughout the application scope; they are widely used to have a single connection to the database and avoid saturating or the famous race conditions (how could it happen to us in Android with SQLite databases), user data and a long etc.

Conclusions

As you can see, Companion Objects are very useful when working with structures that must have a single instance, such as user data, or database connection data in Android.

You can consult the official documentation in the following link: Companion Objects

Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.