Convenciones de nomenclatura
Parte de la sección Object Oriented Programming del Journey de Lua de Coddy — lección 43 de 70.
En Lua, todos los campos de las tablas son accesibles públicamente por defecto. Cualquiera puede leer o modificar self.health directamente. Aunque Lua no impone la privacidad, los programadores utilizan convenciones de nomenclatura para comunicar su intención, señalando qué campos deben tratarse como detalles de implementación interna.
La convención estándar es anteponer un guion bajo a los campos privados:
local Player = {}
Player.__index = Player
function Player:new(name)
local obj = {
name = name, -- Público: está bien acceder directamente
_health = 100, -- Privado: usar métodos en su lugar
_score = 0 -- Privado: seguimiento interno
}
setmetatable(obj, Player)
return obj
end
function Player:getHealth()
return self._health
end
function Player:takeDamage(amount)
self._health = self._health - amount
endEl guion bajo no cambia el funcionamiento de Lua—player._health sigue siendo técnicamente accesible. Sin embargo, sirve como una advertencia clara para otros programadores (y para ti mismo en el futuro): "Este campo está destinado a ser privado. Accede a él a través de métodos en su lugar."
Esta convención es importante porque separa la interfaz (lo que otros deben usar) de la implementación (cómo funciona internamente). Si más adelante necesitas añadir validación o cambiar cómo se almacena la salud, solo modificas los métodos; el código que utiliza :getHealth() sigue funcionando sin cambios.
Desafío
Fácil¡Vamos a construir una clase BankAccount que señale adecuadamente qué campos están destinados a ser privados utilizando la convención de nomenclatura del guion bajo!
Organizarás tu código en dos archivos:
BankAccount.lua: Crea una clase que gestione la información de la cuenta. El constructor:new(ownerName, initialBalance)debe almacenar el nombre del propietario como un campo público (owner) y el saldo como un campo privado (_balance). Incluye tres métodos::getBalance()— devuelve el saldo actual:deposit(amount)— añade la cantidad a_balance:getOwner()— devuelve el nombre del propietario
main.lua: Requiere tu módulo BankAccount, lee el nombre del propietario, el saldo inicial y la cantidad a depositar desde la entrada. Crea una cuenta, realiza un depósito y luego imprime el propietario y el saldo final.
Recibirás tres entradas:
- El nombre del propietario
- El saldo inicial (un número)
- La cantidad a depositar (un número)
Tu salida debe constar de dos líneas que muestren el propietario y el saldo final después del depósito:
Owner: {ownerName}
Balance: {finalBalance}Por ejemplo, si las entradas son Maria, 500 y 150, la salida debería ser:
Owner: Maria
Balance: 650Recuerda: el prefijo de guion bajo en _balance señala a otros programadores que este campo debe ser accedido a través de métodos como :getBalance() y :deposit(), no directamente. El campo owner sin guion bajo indica que está bien acceder a él públicamente.
Hoja de referencia
En Lua, todos los campos de las tablas son accesibles públicamente por defecto. Para comunicar qué campos deben tratarse como detalles de implementación interna, utiliza la convención de nomenclatura de guion bajo anteponiendo un guion bajo (_) a los campos privados.
El guion bajo no impone la privacidad; es una señal para otros programadores de que se debe acceder al campo a través de métodos en lugar de hacerlo directamente.
local Player = {}
Player.__index = Player
function Player:new(name)
local obj = {
name = name, -- Público: está bien acceder directamente
_health = 100, -- Privado: usa métodos en su lugar
_score = 0 -- Privado: seguimiento interno
}
setmetatable(obj, Player)
return obj
end
function Player:getHealth()
return self._health
end
function Player:takeDamage(amount)
self._health = self._health - amount
endEsta convención separa la interfaz (lo que otros deben usar) de la implementación (cómo funciona internamente), lo que hace que el código sea más fácil de mantener cuando se necesitan cambios.
Pruébalo tú mismo
-- Requerir el módulo BankAccount
local BankAccount = require('BankAccount')
-- Leer entradas
local ownerName = io.read()
local initialBalance = tonumber(io.read())
local depositAmount = tonumber(io.read())
-- TODO: Crear una nueva BankAccount con ownerName e initialBalance
-- TODO: Realizar un depósito usando el depositAmount
-- TODO: Imprimir el propietario y el saldo final en el formato requerido
-- Formato:
-- Owner: {ownerName}
-- Balance: {finalBalance}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1El concepto de 'self'
Tablas con funciones'self' explícitoLa sintaxis de dos puntosPunto vs. dos puntosResumen - Punto en movimiento4Proyecto: Banco Digital
Configuración del proyectoMétodo de depósito2Patrón de prototipo de clase
El concepto de prototipoVinculación con __indexEl constructor :new()Inicialización de atributosInstancias independientesResumen - Fábrica de coches5Sobrecarga de operadores en POO
Sumar objetosRestar objetosConcatenar objetosComparar objetos (<, >)Resumen - Matemáticas de la billetera8Encapsulamiento
Convenciones de nomenclaturaClosures para privacidadAcceso mediante ClosuresTablas de solo lecturaLógica de validaciónResumen - Bóveda segura11Patrones de diseño (Lite)
Funciones FactoryTabla SingletonPatrón IteradorObserver (Listener)Resumen - Logger Factory3Estado y Comportamiento de los Objetos
Variables de InstanciaMétodos GetterMétodos SetterPropiedades CalculadasFormateo de StringsComprobaciones de IgualdadResumen - Calificación del Estudiante6Fundamentos de la herencia
Configuración de la herenciaHerencia de métodosExtender el constructorAñadir métodos hijosCompartido vs. ÚnicoResumen: Jerarquía de formas