JetBrains está probando en Kotlin 2.5.0 dos mecanismos nuevos llamados Companion Blocks y Companion Extensions, con el objetivo de ampliar la forma de definir miembros asociados a un tipo y mejorar la interoperabilidad entre las distintas plataformas de Kotlin. La empresa afirma que el nuevo diseño abre patrones de programación que no estaban disponibles fácilmente mediante los Companion Objects tradicionales.
¿Qué añade el nuevo mecanismo?
Los miembros asociados a un tipo se utilizan para definir constantes, utilidades y funciones de creación que no pertenecen a un objeto individual, como una constante que representa el vector cero o una función que crea un vector según un ángulo determinado. Anteriormente, este uso dependía de los Companion Objects, mientras que los nuevos bloques companion permiten escribir este tipo de miembros con una sintaxis más cercana a su definición dentro del propio tipo.
Por su parte, las Companion Extensions permiten añadir miembros asociados a cualquier clase o interfaz, incluso cuando el desarrollador no es propietario del código original, y aunque el tipo proceda de Java o no contenga originalmente un Companion Object. Esto significa que es posible ampliar tipos externos sin modificar su definición básica.
Cambios en la compilación y la compatibilidad
El nuevo mecanismo se diferencia de los Companion Objects en su estrategia de compilación. En la plataforma JVM, los Companion Blocks se compilan como miembros static, lo que aproxima su comportamiento al de los miembros estáticos en otras plataformas. JetBrains considera que esto puede beneficiar a Kotlin Multiplatform, ya que se pueden definir miembros esperados en un bloque companion y después implementarlos mediante una clase de Java que contenga miembros static.
Sin embargo, las funciones todavía son experimentales. Para activar Companion Blocks es necesario utilizar la opción -Xcompanion-blocks, mientras que para combinar bloques y extensiones se requiere la opción -Xcompanion-blocks-and-extensions.
Limitaciones del uso experimental
Al utilizar Companion Extensions, el compilador produce archivos binarios previos al lanzamiento. Por ello, es posible que otros proyectos o bibliotecas no puedan consumir como dependencias las bibliotecas que utilicen estas extensiones hasta que la función se estabilice oficialmente. La misma limitación no se aplica a la exposición de Companion Blocks, pero sus usuarios también deberán activar la función.
¿Deben migrarse los Companion Objects?
JetBrains no recomienda una migración inmediata. Los Companion Objects siguen siendo una parte fundamental de Kotlin y su compatibilidad total está garantizada. Los Companion Blocks pueden ser la opción preferida para el código nuevo en la mayoría de los casos, pero los Companion Objects siguen siendo necesarios en determinadas situaciones, como cuando el companion necesita implementar una interfaz, ya que se compilan como una clase completa.
En la práctica, en muchos casos puede bastar con eliminar la palabra object para pasar a un Companion Block, pero tanto el proyecto como todo el código que dependa de él deberán recompilarse. JetBrains también advierte que algunas herramientas del ecosistema quizá aún no estén preparadas para manejar la nueva sintaxis.
¿Por qué es importante este avance?
El cambio es importante para los desarrolladores de Kotlin Multiplatform y los autores de bibliotecas, porque intenta reducir la brecha entre el concepto de los miembros estáticos en la JVM y en otras plataformas. Sin embargo, su valor práctico actual sigue estando ligado a una fase experimental y a la rapidez con la que se actualicen las herramientas de compilación, las bibliotecas y los editores. Por eso, los Companion Blocks parecen adecuados para experimentar y evaluar el diseño, pero no como base segura para una migración amplia antes de que la función se estabilice.