Módulos y pub
Repartir un programa en archivos con usar, y decidir qué se comparte con pub.
Cuando un programa crece, se reparte en archivos. Cada archivo .cometa es un módulo, y usar trae uno a otro.
Importar con usar
La ruta es relativa al archivo que importa, con / como separador y sin extensión. Las declaraciones del módulo quedan bajo su nombre (el último segmento de la ruta):
usar modulos/temperatura
fn inicio()
imprimir(temperatura.a_fahrenheit(25.0))
Con como eliges otro nombre, útil si es largo o si choca con algo tuyo:
usar modulos/temperatura como temp
fn inicio()
imprimir(temp.a_fahrenheit(25.0))
./ y ../ suben o se quedan en la carpeta: usar ../compartido/fechas. Los usar van siempre al principio del archivo, antes de cualquier declaración.
Qué se comparte: pub
Todo es privado al archivo por defecto. Para que otro archivo lo use, se marca con pub: funciones, constantes, variables, tipos, enums e interfaces. Dentro de un tipo, cada campo y cada método se marca por separado, así puedes esconder los detalles internos:
// tienda/cuenta.cometa
pub tipo Cuenta
pub titular cadena
saldo entero // privado: solo este archivo lo toca
pub fn depositar(monto entero)
si monto > 0
@saldo += monto
pub fn saldo_actual() entero @saldo
pub fn nueva(titular cadena) Cuenta
Cuenta {titular: titular}
// sin pub: un detalle interno de este archivo
fn validar(monto entero) bool monto > 0
Se usa con el nombre del módulo delante, tanto para funciones como para tipos:
// principal.cometa
usar tienda/cuenta como c
fn inicio()
var ana = c.nueva("Ana")
ana.depositar(50)
imprimir("${ana.titular}: ${ana.saldo_actual()}") // Ana: 50
Lo que no es pub no se puede tocar desde fuera. El compilador lo dice claramente:
ana.saldo = 1000000 // error: el miembro "saldo" es privado
c.validar(5) // error: la declaración "validar" es privada en el módulo …
Así Cuenta controla su saldo: solo cambia a través de depositar. Esa es la idea de pub: mostrar lo que otros necesitan y esconder el resto para poder cambiarlo después sin romper a nadie.
Desde otro archivo, un literal solo puede dar valor a los campos pub; los privados se quedan con su valor por defecto:
var x = c.Cuenta {titular: "Ana"} // válido: saldo empieza en 0
var y = c.Cuenta {titular: "Ana", saldo: 99} // error: el campo "saldo" es privado
Si un campo privado necesita un valor inicial concreto, el módulo debe ofrecer una función constructora, como nueva.
Reglas a recordar
- Solo el archivo principal declara
inicio. - Los
usarno se reexportan: siausab, quien useano obtieneb; debe importarlo él. - Los ciclos (
ausabybusaa) y los imports repetidos se rechazan. pubno va en variables locales, parámetros ni enusar.- La biblioteca estándar se importa igual:
usar std/mate,usar std/pincel/graficos… (mira la biblioteca).
Programa completo
// Módulos: repartir el programa en varios archivos.
// usar importa modulos/temperatura.cometa, relativo a este archivo.
usar modulos/temperatura
fn inicio()
var grados = 25.0
imprimir("${grados} °C son ${temperatura.a_fahrenheit(grados)} °F")
imprimir(temperatura.describir(grados))
// Solo lo marcado con pub en el módulo es visible aquí.
imprimir("El agua hierve a ${temperatura.ebullicion} °C")