Lua Orientada a Objetos
Avançado !
Lua é uma linguagem de programação(Sério??) , sua orientação a tabelas, meta tabelas, meta métodos é bem prático e versátil.
* Meta tabelas *
O que é uma meta tabelas?
São tabelas que controla o comportamento de outras estruturas de dados, ela nos permiti alterar o comportamento da tabela.
Exemplo, se colocar o código abaixo num interpretador Lua.
nome = "Xtibia Forum de Tibia"print(nome:upper())
A saída será: XTIBIA FORUM DE TIBIA
Porém, da onde saiu esse upper()? Vejamos.. print(getmetatable(nome))
Sua saída será: table: 0033BE78
Uma meta tabela associado a string !!, vejamos: print(getmetatable(nome).__index == string)
Sua saída será: true
ou seja concluímos que a chave __index da meta tabelas é módulo de uma string: como exemplo nome:upper() == nome.upper(nome) == string.upper(nome)
*Chave __index*
A chave __index da meta tabela pode ser uma tabela ou uma função e indica o que deve acontecer quando houver uma tentativa de leitura de uma chave que a estrutura de dados original não possuía Se o objeto referenciado pela variável nome(uma string) não possui a chave upper, então quando tentamos acessar esta chave, o sistema procura pela chave na tabela referenciada pela chave __index da meta tabela, que é uma string
Caso queiramos que ela retorna um valor da tabela ASCII, podemos utilizar está função mt = {__index = function (t, k)return k:byte()end}var = setmetatable({b}, mt)print(var)
Vale lembrar que essa chave é importante para orientação a objetos.
* Classes e Construtores *
Em orientação a objeto, classe é um molde para a criação de novos objetos, em Lua,classe em geral é uma meta tabela onde a chave __index aponta para ela própria.
Exemplo abaixo: mt = {}mt.__index = mt
Meta tabelas se torna um molde para as outras tabelas. As tabelas que fazem o uso deste molde são chamadas de instâncias. As funções de uma classe/instância são chamadas de métodos e sempre recebem implícita ou explicitamente como primeiro argumento a classe ou instância que faz a chamada. Lua pode chamar um método passando a instância (ou classe) implícita ou explicitamente
Exemplo de uma chamada explícita: login = login.lower(login)
Exemplo de uma chamada , passando a instância implicitamente login = login:lower()
Existe um método especial chamado construtor, que é executado sempre que uma nova instância é criada.
Vejamos: function mt:new(o)o = o or {}return setmetatable(o, self)end
O construtor do código a cima recebe como um argumento uma tabela que servirá de referência para a criação da instância.
O primeiro comando garante que o argumento o é uma tabela, o segundo associa a meta tabela ao objeto, retornando-o. Como new()é um método de classe, self representa a classe. Se fosse um método de instância, self representaria a instância.
* Outros métodos *
Podemos criar outros métodos. Por exemplo queremos criar um somatório dos elementos números da tabela seja retornado para o método soma()
Exemplo function mt:soma()local s = 0table.foreachi(self, function (i, e)if type(e) == "number" thens = s + eendend)return send
Podemos criar um objeto com alguns valores números e retornar seu somatório: var = mt:new { 2, 4, 6 }ret = var:soma()print (ret)
Que imprimirá: 12
*Meta Métodos*
Apenas irei citar alguns, caso tenha curiosidade procure sobre. __add – gerencia operador de adição;
__sub – gerencia operador de subtração;
__mul – gerencia operador de multiplicação;
__div – gerencia operador de divisão;
__unm – gerencia operador unário de negação;
__eq – gerencia operador de igualdade;
__lt – gerencia operadores menor que e igual ou maior;
__le – gerencia operadores menor ou igual e maior que;
__pow – gerencia operador de potência;
__tostring – gerencia conversão para string;
__tonumber – gerencia conversão para número.
* Herança *
Queremos outra classe que além de devolver a soma, também devolva o produto, mas sem modificar a classe original. Para isso herdamos uma nova classe, para isso precisamos instanciar a classe pai normalmente, modificar a instância e usar esta instância como uma nova classe
Exemplo function nmt:produto()local p = 1]table.foreachi(self, function (i, e)if type(e) == "number" thenp = p * eendend)return pendvar = nmt:new { 2, 4, 6 }[size=4]print(var:soma(), var:produto())
Imprimirá: 48
Há outra forma mais avançada de herança, chamada herança múltipla, que acontece quando uma classe é herdeira de mais de uma classe pai. Fim.
Mega Tutorial OOP em Lua