Postado Novembro 21, 2012 12 anos Este é um post popular. Metamétodos Bem, talvez não seja útil a todos (ou apenas não vejam a utilidade disso no começo), mas como já tinha feito um tutorial de POO em lua decidi me aprofundar mais e entrar em um assunto que não tem muita gente que sabe, ter um conhecimento intermediário sobre POO ajuda a aprender isso (saber usar a função setmetatable também), mas apenas um complementa o outro como veremos logo a seguir. Porque aprender ? Se eu dissesse que isso é necessário para programar eu estaria mentindo, mas pode acabar sendo útil, quem sabe para complementar o conhecimento de POO, mas é como eu já disse no outro tópico, aprende quem quiser. Metamétodos Metamétodos são (obviamente) associados a metatabelas, esses "métodos" são basicamente os eventos que ocorrem quando Lua (a linguagem) executa algumas operações: subtração, divisão, comparações, concatenações etc. É o que chamam em algumas linguagens de sobrecarregar operador (basicamente é a mesma coisa), cada evento tem um nome, adição é "add", exponenciação é "pow", concatenação é "concat", mais a frente eu cito todos e suas funções. Um exemplo, que caso você já saiba POO já deve ter visto é esse: Classe = {} function Classe:new() return setmetatable({}, { __index = self }) end Esse __index, já se perguntou o que ele faz ali ? Ele é um metamétodo também, ele simplesmente mostra que é para procurar indices(seja métodos, atributos, oque for) na tabela self (ou seja, nela mesma), e é por isso que quando você cria uma classe você consegue usar os métodos (não confunda com metamétodos), atributos dela. O 2º parametro da função setmetatable é uma tabela de metamétodos. Exemplo: metatable = {} function String(s) return setmetatable({ value = s or '' }, metatable) end function metatable.__add(a, b) return String(a.value .. b.value) end Veja que eu adicionei o metamétodo __add que se refere ao operador matemático de adição, com esse método você pode fazer isso (a seguir), tente executar e veja o resultado: s = String('Hello') print("Valor de 's' é: " .. s.value) m = s + String(' World') print("Soma de duas Strings: " .. m.value) Agora apague tudo e tente dessa maneira sem o metamétodo: metatable = {} function String(s) return setmetatable({ value = s or '' }, metatable) end s = String('Hello') print("Valor de 's' é: " .. s.value) m = s + String(' World') print("Soma de duas Strings: " .. m.value) Vai resultar em um erro. A partir disso você pode criar muitas coisas ! o exemplo acima (o que funciona) também pode ser escrito dessa maneira: function String(s) return setmetatable({ value = s or '' }, { __add = function(a,b) return String(a.value .. b.value) end }) end s = String('Hello') print("Valor de 's' é: " .. s.value) m = s + String(' World') print("Soma de duas Strings: " .. m.value) Eu pulei linha ali no setmetatable apenas pra ficar mais organizado e de fácil entendimento, não que seja necessário. Basicamente, metamétodos são os métodos que fazem operações em metatabelas lua, agora veja o mesmo exemplo acima mas sem o metamétodo: String = {} function String:new(s) return setmetatable({ value = s or '' }, { __index = self }) end function String:add(s) self.value = self.value .. s.value return self.value end s = String:new('Hello') print("Valor de 's' é: " .. s.value) m = s:add(String:new(' World')) print("Soma de duas Strings: " .. m) O uso ficaria um pouco mais complicado e não daria a liberdade de você fazer isso (em negrito): s = String('Hello') print("Valor de 's' é: " .. s.value) m = s + String(' World') + String(' and ') + String('Universe') print("Soma de quatro Strings: " .. m.value) Soma de quatro objetos String ao mesmo tempo (em negrito) --- A tabela com os metamétodos, toma-se class1 como um objeto de uma classe qualquer e class2 como um outro objeto da mesma classe de class1, ou numero, ou string, ou tabela, ou userdata, ou thread ou qualquer outro tipo de dado lua: As cores não estão ali a toa, Função/Nome = o nome e função do metamétodo; Uso = Como se deve usar; Parâmetros = Quais parâmetros o metamétodo possui; Exemplo = Exemplo de quando o metamétodo irá acontecer. Você pode encontrar todas os metamétodos junto a um exemplo nesse link http://www.lua.org/manual/5.1/pt/manual.html#2.8, mas vou citar alguns exemplos: TV = {} function TV:new(marca, polegadas) return setmetatable({ marca = marca or '', polegadas = polegadas or '' }, { __add = function (tv, n) -- Metamétodo de adição if (type(n) == 'number') then return TV:new(tv.marca, tv.polegadas + n) else return TV:new(tv.marca, tv.polegadas + n.polegadas) end end, __mul = function (tv, n) -- Metamétodo de multiplicação return TV:new(tv.marca, tv.polegadas * n) end, __eq = function (tv1, tv2) -- Metamétodo de igualdade if (tv1.marca == tv2.marca and tv1.polegadas == tv2.polegadas) then return true end return false end }) end tv1 = TV:new("LG", 21) tv2 = TV:new("Philips", 19) tv1 = tv1 + 4 -- Adiciono 3 a tv1 print(tv1.polegadas) -- tv1 fica com 25 polegadas tv2 = tv1 + tv2 -- Adiciono as polegadas da tv1 na tv2 print(tv2.polegadas) tv1 = tv1 * 2 -- Multiplico as polegadas da tv1 por 2 print(tv1.polegadas) if (tv1 == tv2) then print('tv1 é igual a tv2 !') else print('tv1 não é igual a tv2') end tv1 = tv2 -- Agora tv1 é igual a tv2 if (tv1 == tv2) then print('tv1 é igual a tv2 !') else print('tv1 não é igual a tv2') end O exemplo é ruim eu sei, mas to sem criatividade D: Explicação detalhada: Agora uma explicação passo a passo de um metamétodo, vou aproveitar o da TV: __add = function (tv, n) -- Metamétodo de adição if (type(n) == 'number') then return TV:new(tv.marca, tv.polegadas + n) else return TV:new(tv.marca, tv.polegadas + n.polegadas) end end e uma soma qualquer: tv1 = tv1 + 4 O metamétodo tem 2 parametros, tv e n (você pode escolher o nome que quiser), tv e n referem-se a tv1 e 4 na soma respectivamente, ou seja, o __add (linha 1) vai verificar se o n é um numero (linha 2) e caso for ele vai retornar outro objeto da classe TV , com a mesma marca da tv mas com as polegadas somadas ao numero n (linha 3) , mas caso não for um numero (linha 4) vai manter a marca da tv e somar as polegadas da tv e da TV n (linha 5) . Novamente, as cores (e o negrito) não estão ali a toa. Bem é um pouco complicadinho, mas todos (a maioria) dos metamétodos seguem esse mesmo padrão de 2 parametros, ai facilita um pouco --- Espero que alguém tenha compreendido, tentei ser o mais claro possível, caso contrario eu refaço as partes que estão complicadas, Qualquer dúvida, sugestão, critica, só postar ! Quem quiser pode me enviar sugestões de temas para tutoriais sobre scripting e programação, algum assunto que não entendeu, que não viu no forum ou que faltou algo mais detalhado. Creditos Lwkass Contato; god.marinii [email protected]
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.