Objetos Compañeros En Kotlin

En este tutorial aprenderás sobre otro uso de la palabra reservada object, para declarar objetos compañeros en Kotlin.

Objetos Compañeros

Un objeto compañero o companion object es la representación de un miembro que se puede llamar directamente del nombre de una clase, sin la creación previa de una instancia de dicha clase.

Se podría decir que es el equivalente a los miembros estáticos de Java, solo que en Kotlin no existe la palabra static.

Declaración De Objetos Compañeros

Su declaración se basa en crear una declaración de objeto anidada en la clase, pero anteponiendo la palabra reservada companion.

El nombre del objeto compañero es opcional, por lo que es posible ubicar las llaves del cuerpo inmediatamente a la palabra object.

class ClaseEjemplo {
    // Declaración de objeto compañero
    companion object {
        val propiedad: Int = 10

        fun metodo() = print("Método")
    }
}

En el ejemplo anterior ClaseEjemplo representa a la clase externa, en donde declaras un companion object con una propiedad con el valor de 10 y un método que imprime el String "Método".

Acceso A Objetos Compañeros

La declaración anterior te permite acceder a los miembros del objeto compañero a través del nombre de la clase sin tener que crear una instancia primero.

fun main() {
    // Acceso a miembros sin creación de instancia
    ClaseEjemplo.propiedad
    ClaseEjemplo.metodo()
}

En el caso anterior accedemos a propiedad y metodo() usando el nombre ClaseEjemplo.

Objetos Regulares

Es necesario saber que un objeto compañero sigue siendo compilado como una expresión de objeto regular, por lo que es posible:

  • Especificarle un nombre
  • Aplicarle herencia
  • Implementarle interfaces
  • Declararle funciones y propiedades de extensión

Inclusive, en el acceso redundante de la sintaxis, se usaría el identificador Companion para un objeto compañero sin nombre:

ClaseEjemplo.Companion.metodo()

Si estableces un nombre particular, entonces usas la referencia a dicho nombre.

Ejemplo De Objetos Compañeros En Kotlin

Uno de los usos más significativos para los objetos compañeros es la creación de métodos de fabricación.

Por ejemplo, supongamos que deseamos construir un rectángulo basado en el alto y ancho. Pero deseamos contemplar la opción de creación donde ambos parámetros son iguales.

Es posible usar un objeto compañero con ambos métodos de fabricación en como reemplazo de una posible sobrecarga de constructores.

class Rect private constructor(val witdh: Int, val heigth: Int) {
    val area = witdh * heigth

    companion object {
        fun create(witdh: Int, heigth: Int): Rect = Rect(witdh, heigth)
        fun create(size: Int): Rect = Rect(size, size)
    }
}

Como ves, el objeto compañero contiene dos métodos create() que retornan en una instancia de Rect al llamar a su constructor primario privado.

Donde el segundo método usa un único parámetro size que es pasado como alto y ancho. El uso de ambos métodos podemos verlo en el siguiente código:

fun main() {

    val rect1 = Rect.create(5, 10)
    val rect2 = Rect.create(10)

    println("Área 1: ${rect1.area}, Área 2: ${rect2.area}")
}

Resultado:

Área 1: 50, Área 2: 100

Funciones De Extensión En Objetos Compañeros

Como habíamos dicho antes, es posible declarar funciones de extensión en objetos compañeros. La sintaxis se resume al uso de Companion como el tipo recibidor.

Tomemos como base el ejemplo del rectángulo, supongamos que deseas añadir una forma de crear instancias pero desde un archivo en el disco del sistema.

Ya que esta fuente de datos no hace parte de la creación que establecimos en el dominio y además deseamos mantener limpia a la clase Rect, creamos una función de extensión que realice la interpretación del archivo y mapee la instancia.

import java.io.File
fun Rect.Companion.fromFile(file: File): Rect {
    // Lectura del archivo...
    val witdhFromFile = 1
    val heigthFromFile = 2
    return create(witdhFromFile, heigthFromFile)
}

Ya que Companion es el recibidor, create() puede llamarse directamente. El lugar de ubicación de esta función será el módulo o paquete donde estés manejando la capa de datos.

Ahora, si deseas llamar a la función de extensión, usas el nombre de la clase Rect directamente:

val rectFromFile = Rect.fromFile(rectFile)

Únete Al Discord De Develou

Si tienes problemas con el código de este tutorial, preguntas, recomendaciones o solo deseas discutir sobre desarrollo Android conmigo y otros desarrolladores, únete a la comunidad de Discord de Develou y siéntete libre de participar como gustes. ¡Te espero!