Introducción
En Scala, los objetos compañeros (companion objects) son una característica poderosa que permite definir métodos y valores que están estrechamente relacionados con una clase, pero que no requieren una instancia de la clase para ser utilizados. Los objetos compañeros se definen utilizando la palabra clave object
y deben tener el mismo nombre que la clase a la que acompañan. Esta relación especial permite que el objeto y la clase accedan a los miembros privados entre sí.
Conceptos Clave
- Objeto Compañero: Un objeto que comparte el mismo nombre que una clase y se define en el mismo archivo fuente.
- Métodos de Fábrica: Métodos en el objeto compañero que crean instancias de la clase.
- Acceso a Miembros Privados: Los objetos compañeros y las clases pueden acceder a los miembros privados entre sí.
Definición de un Objeto Compañero
Para definir un objeto compañero, simplemente se utiliza la palabra clave object
seguida del nombre del objeto, que debe coincidir con el nombre de la clase. Aquí hay un ejemplo básico:
class Persona(val nombre: String, val edad: Int) { // Miembros de la clase private def mostrarInfo(): String = s"Nombre: $nombre, Edad: $edad" } object Persona { // Método de fábrica def apply(nombre: String, edad: Int): Persona = new Persona(nombre, edad) // Método para crear una Persona a partir de una cadena def fromString(info: String): Persona = { val partes = info.split(",") new Persona(partes(0), partes(1).toInt) } }
En este ejemplo:
- La clase
Persona
tiene un constructor que toma dos parámetros:nombre
yedad
. - El objeto
Persona
define un métodoapply
que actúa como un método de fábrica para crear instancias dePersona
. - También define un método
fromString
que crea una instancia dePersona
a partir de una cadena.
Uso de Objetos Compañeros
Los objetos compañeros se utilizan para definir métodos y valores que están relacionados con la clase, pero que no dependen de una instancia específica. Aquí hay algunos ejemplos de cómo se pueden utilizar:
Métodos de Fábrica
Los métodos de fábrica son métodos en el objeto compañero que crean instancias de la clase. Esto es útil cuando se necesita lógica adicional para crear instancias.
Acceso a Miembros Privados
Los objetos compañeros y las clases pueden acceder a los miembros privados entre sí. Esto permite encapsular la lógica de manera efectiva.
class CuentaBancaria(private var saldo: Double) { def depositar(cantidad: Double): Unit = { saldo += cantidad } def retirar(cantidad: Double): Unit = { if (cantidad <= saldo) saldo -= cantidad else throw new IllegalArgumentException("Fondos insuficientes") } } object CuentaBancaria { def crearCuentaInicial(saldoInicial: Double): CuentaBancaria = { new CuentaBancaria(saldoInicial) } }
En este ejemplo, el objeto CuentaBancaria
puede acceder al miembro privado saldo
de la clase CuentaBancaria
.
Ejercicio Práctico
Ejercicio 1: Definir un Objeto Compañero
Define una clase Libro
con los siguientes atributos: titulo
(String) y autor
(String). Luego, define un objeto compañero que incluya un método de fábrica apply
y un método fromCSV
que cree una instancia de Libro
a partir de una cadena CSV.
class Libro(val titulo: String, val autor: String) object Libro { def apply(titulo: String, autor: String): Libro = new Libro(titulo, autor) def fromCSV(csv: String): Libro = { val partes = csv.split(",") new Libro(partes(0), partes(1)) } }
Solución
val libro1 = Libro("1984", "George Orwell") val libro2 = Libro.fromCSV("Brave New World,Aldous Huxley") println(s"Libro 1: ${libro1.titulo} por ${libro1.autor}") println(s"Libro 2: ${libro2.titulo} por ${libro2.autor}")
Ejercicio 2: Acceso a Miembros Privados
Modifica la clase Libro
para que tenga un miembro privado precio
(Double) y define un método en el objeto compañero que permita actualizar el precio de un libro.
class Libro(val titulo: String, val autor: String, private var precio: Double) { def mostrarInfo(): String = s"Titulo: $titulo, Autor: $autor, Precio: $$precio" } object Libro { def apply(titulo: String, autor: String, precio: Double): Libro = new Libro(titulo, autor, precio) def fromCSV(csv: String): Libro = { val partes = csv.split(",") new Libro(partes(0), partes(1), partes(2).toDouble) } def actualizarPrecio(libro: Libro, nuevoPrecio: Double): Unit = { libro.precio = nuevoPrecio } }
Solución
val libro3 = Libro("El Hobbit", "J.R.R. Tolkien", 15.99) println(libro3.mostrarInfo()) Libro.actualizarPrecio(libro3, 12.99) println(libro3.mostrarInfo())
Conclusión
Los objetos compañeros en Scala son una herramienta poderosa para definir métodos y valores que están estrechamente relacionados con una clase, pero que no requieren una instancia de la clase para ser utilizados. Permiten la creación de métodos de fábrica, el acceso a miembros privados y la encapsulación de lógica relacionada con la clase. Al dominar los objetos compañeros, puedes escribir código más limpio y organizado en Scala.
En el próximo tema, exploraremos los objetos singleton, que son otra característica importante de Scala para definir objetos únicos en tu aplicación.
Curso de Programación en Scala
Módulo 1: Introducción a Scala
- Introducción a Scala
- Configuración del Entorno de Desarrollo
- Conceptos Básicos de Scala: Sintaxis y Estructura
- Variables y Tipos de Datos
- Operaciones Básicas y Expresiones
Módulo 2: Estructuras de Control y Funciones
- Sentencias Condicionales
- Bucles e Iteraciones
- Funciones y Métodos
- Funciones de Orden Superior
- Funciones Anónimas
Módulo 3: Colecciones y Estructuras de Datos
- Introducción a las Colecciones
- Listas y Arreglos
- Conjuntos y Mapas
- Tuplas y Opciones
- Coincidencia de Patrones
Módulo 4: Programación Orientada a Objetos en Scala
- Clases y Objetos
- Herencia y Rasgos
- Clases Abstractas y Clases Caso
- Objetos Compañeros
- Objetos Singleton
Módulo 5: Programación Funcional en Scala
- Inmutabilidad y Funciones Puras
- Estructuras de Datos Funcionales
- Mónadas y Funtores
- Comprensiones For
- Manejo de Errores en Programación Funcional
Módulo 6: Conceptos Avanzados de Scala
- Conversiones y Parámetros Implícitos
- Clases de Tipo y Polimorfismo
- Macros y Reflexión
- Concurrencia en Scala
- Introducción a Akka