Bienvenidos sean a este post, continuando con el post anterior hoy nos cruzaremos con el primer problema: como podemos crear varios objetos con la misma conducta? mas especificamente como podemos crear varias cuentas?

Anuncios

Para ello usaremos clases, una clase trabaja como un molde para la creacion de objetos, para el que tiene un poco de conocimiento sabe que los lenguajes orientados a objetos ofrecen un concepto de clase, en tales lenguajes cada objeto es una instancia de una clase especifica, Lua no posee el concepto de la clase, cada objeto define su propia conducta y tiene una forma propia, sin embargo no es muy dificil emular clases en Lua siguiendo el ejemplo de los lenguajes basados en prototipos como Self y NewtonScript, en estos lenguajes los objetos no tienen clases en su lugar cada objeto podria tener un prototipo el cual es un objeto regular donde el primer objeto busca cualquier operacion que no sabe al respecto, para representar una clase en tales lenguajes simplemente creamos un objeto para ser usado exclusivamente como un prototipo para otros objetos (sus instancias), ambas clases y prototipos trabajan como un lugar para poner la conducta a ser compartida por varios objetos.

Anuncios

En Lua la implementacion de prototipos es algo trivial pero con el uso de herencias, tal como vimos en este post, mas especificamente si tenemos dos objetos, a y b, todo lo que tenemos que hacer a b un prototipo de a como se ve a continuacion:

setmetatable(a, { __index = b })

Despues de esto, a mira en b por cualquier operacion que no tenga, para ver b como la clase del objeto a no es mas que un cambio en la terminologia, volvamos al ejemplo del post anterior con la cuenta bancaria, para crear otras cuentas con una conducta similar a Cuenta debemos ordenar estos nuevo objetos para heredar sus operaciones desde Cuenta gracias al metametodo __index, una pequeña optimizacion es que no necesitamos crear una tabla extra para ser la metatabla de los objetos cuenta y para ello usamos la tabla de Cuenta para este proposito:

function Cuenta:nuevo(o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end
Anuncios

Cuando llamamos a Cuenta:nuevo, self es igual a Cuenta asi que podriamos haber usado Cuenta directamente en lugar de self sin embargo el uso de self encargara de forma mas “monona” la implementacion cuando introduzcamos una herencia de clase, mas adelante hablaremos sobre esto, veamos que sucede despues de esto:

a = Cuenta:nuevo{ balance = 0 }
a:depositar(100.00)

Cuando se crea la nueva cuenta a tendra a Cuenta (el self en la llamada a Cuenta:nuevo) como su metatabla, luego cuando usamos :

a:depositar(100.0) 

En realidad estamos llamando a:

a.depositar(a,100.0) 
Anuncios

En este caso el separador es una forma mas agradable de llamar a la funcion, sin embargo Lua no puede encontrar una entrada “depositar” en la tabla a, asi que mira dentro de la entrada __index de la metatabla, esto equivale al siguiente codigo:

getmetatable(a).__index.depositar(a, 100.00)

La metatabla de a es Cuenta y Cuenta.__index tambien es Cuenta porque el metodo nuevo hizo:

self.__index = self 

Por lo tanto la expresion anterior se reduce a:

Cuenta.depositar(a, 100.0)
Anuncios

En este caso Lua llama a la funcion depositar original pero pasando la variable a como el parametro self, asi que la nueva cuenta a hereda la funcion depositar desde Cuenta y por el mismo mecanismo puede heredar todos los campos de Cuenta, la herencia no trabaja solo para metodos sino tambien para otros campos que estan ausentes en la nueva cuenta, asi una clase no solamente provee metodos sino tambien valores predeterminados para sus campos instanciados, observen que en nuestra primera definicion de Cuenta le dimos un campo llamado balance con el valor de 0 y si creamos una nueva cuenta sin un balance inicial esta heredara el valor predeterminado:

b = Cuenta.nuevo()
print(b.balance)	// Devuelve 0

Y cuando llamemos a la funcion depositar en b equivaldria a esto:

b.balance = b.balance + v

Porque self ahora es b, la expresion b.balance evalua a cero y un deposito inicial es asignado a b.balance, los accesos siguientes a b.balance no invocaran el metametodo __index porque ahora tiene su propio campo balance.

Anuncios

En resumen, hoy hemos visto clases, un repaso general de como es en otros lenguajes, como se puede crear en Lua, como se puede implementar y los beneficios que nos entrega, espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00