Metatabelas Lua

Neste artigo, exploraremos o conceito de metatabelas Lua , como usá-las e alguns exemplos práticos.

As tabelas que definem o comportamento de outras tabelas são conhecidas como metatabelas.



Lua Metatables – O que são?

A metatabela Lua é uma tabela associada a outra tabela e que fornece funcionalidade adicional a essa tabela.

Uma metatabela pode ser usada para personalizar o comportamento de tabelas de várias maneiras, como alterar como Lua realiza operações aritméticas nelas ou adicionar novos métodos e propriedades às tabelas.

As metatabelas também podem ser usadas para criar tipos de dados personalizados em Lua e para implementar técnicas de programação orientada a objetos.

Em Lua, toda tabela pode ter uma metatabela associada a ela, e essa metatabela pode ser acessada e modificada usando as funções setmetatable e getmetatable.

A função setmetatable define a metatabela de uma tabela, enquanto a função getmetatable recupera a metatabela de uma tabela.


Setmetatable(tabela,metatabela)

Este método define a metatabela de uma tabela. Aqui ' table ' é a tabela cuja metatabela deve ser definida e ' metatable ' é a nova metatabela a ser atribuída à tabela.

O exemplo a seguir ilustra a função setmetatable() em Lua:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
-- Define a table
local myTable = { 2, 4, 6, 8, 10 }
-- Define a metatable with custom behavior
local myMetatable = {
__tostring = function(t)
return "This is myTable with values: " .. table.concat(t, ", ")
end,
__add = function(t1, t2)
local result = {}
for i = 1, #t1 do
result[i] = t1[i] + t2[i]
end
return result
end
}
-- Set the metatable for myTable
setmetatable(myTable, myMetatable)
-- Use the __toString metamethod
print(myTable)
local myOtherTable = { 1, 2, 3, 4, 5 }
-- Use the __add metamethod to add two tables
local sum = myTable + myOtherTable
print('Values after using __add metamethod:',table.concat(sum, ", "))
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Getmetatable(tabela)

Este método obtém a metatabela de uma tabela. A função getmetatable() recebe um único argumento, que é a tabela cuja metatabela queremos recuperar.
Se a tabela tiver uma metatabela, getmetatable() a retornará.
Se a tabela não tiver uma metatabela, getmetatable() retornará nil.
O exemplo abaixo explica o uso do método getmetatable() :

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-- Define a table and a metatable
local mytable = {a = 1, b = 2}
local mymetatable = {c = 3, d = 4}
-- Set the metatable for the table
setmetatable(mytable, mymetatable)
-- Get the metatable for the table
local retrievedMetatable = getmetatable(mytable)
if retrievedMetatable == mymetatable then
print("Retrieved metatable is the same as the original metatable")
else
print("Retrieved metatable is NOT the same as the original metatable")
end
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Metamétodos Lua

Metamétodos são métodos especiais em Lua associados a metatabelas e definem o comportamento de operadores e funções internas quando aplicados a tabelas.

Em outras palavras, os metamétodos fornecem uma maneira de estender ou modificar o comportamento dos operadores e funções integrados de Lua quando aplicados a tabelas.

Metatabelas Lua devem primeiro ser criadas como tabelas regulares antes de poderem ser usadas.

Existem vários metamétodos em Lua, cada um correspondendo a um operador ou função interna específica.

Um ou mais dos seguintes metamétodos devem ser incluídos nesta tabela:

__índice

Usado quando uma chave inexistente é usada para indexar a tabela.

Aqui está um exemplo que usa o metamétodo __index :

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
-- Define a table with some default values
local myTable = {
name = "John",
age = 35,
occupation = "Programmer"
}
-- Define a new table with a metatable that has an __index metamethod
local myMetatable = {
__index = function(table, key)
if key == "gender" then
return "Male"
else
return "Unknown"
end
end
}
-- Set the metatable for myTable to myMetatable
setmetatable(myTable, myMetatable)
-- Try to access a key that doesn't exist in myTable
print(myTable.address) -- Output: Unknown
-- Try to access the "gender" key that doesn't exist in myTable but specified using __index
print(myTable.gender) -- Output: Male
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__newindex

Quando um novo índice é definido em uma tabela, essa função é chamada.

O exemplo abaixo examina o método __newindex em Lua:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
local mytable = {}
local mymetatable = {
__newindex = function (table, key, value)
print("Assigning value " .. value .. " to key " .. key)
end
}
setmetatable(mytable, mymetatable)
mytable.name = "Harry"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__para sequenciar

Este método nos permite definir como um objeto deve ser convertido em uma string quando é impresso.

Este método é chamado pela função tostring() quando é chamado em um objeto.

O exemplo a seguir simplifica o entendimento do método __toString :

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
local mytable = {name = "Harry", age = 35}
local table_metatable = {
__tostring = function(table)
return "Name: " .. table.name .. ", Age: " .. table.age
end
}
setmetatable(mytable, table_metatable)
print(mytable)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__adicionar

Esta função é chamada quando dois valores são adicionados.

Vamos explorar um exemplo onde _add é implementado:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with an __add metamethod
local myMetatable = {
__add = function(table1, table2)
return {value = table1.value + table2.value}
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 5
local anotherTable = {value = 5}
-- add the two tables together
local result = myTable + anotherTable
-- print the result
print(result.value)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__sub

Este método é acionado quando dois valores são subtraídos com o operador .

O exemplo abaixo mostra a implementação do metamétodo __sub em Lua:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with a __sub metamethod
local myMetatable = {
__sub = function(table1, table2)
return {value = table1.valuetable2.value}
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 5
local anotherTable = {value = 5}
-- subtract the two tables
local result = myTableanotherTable
-- print the result
print(result.value)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__mul

Este método é invocado quando dois valores são multiplicados usando o operador *.

O exemplo a seguir fornece uma visão geral do metamétodo __mul em Lua:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with a __mul metamethod
local myMetatable = {
__mul = function(table1, table2)
return {value = table1.value * table2.value}
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 5
local anotherTable = {value = 5}
-- multiply the two tables together
local result = myTable * anotherTable
-- print the result
print(result.value)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__div

Este método é chamado se dois valores forem divididos usando um operador / .

O método __div é demonstrado no exemplo abaixo:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with a __div metamethod
local myMetatable = {
__div = function(table1, table2)
return {value = table1.value / table2.value}
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 5
local anotherTable = {value = 5}
-- divide the two tables
local result = myTable / anotherTable
-- print the result
print(result.value)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__mod

Usado quando dois valores são divididos usando o operador % .

O exemplo a seguir implementa o metamétodo __mod em Lua:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with a __mod metamethod
local myMetatable = {
__mod = function(table1, table2)
return {value = table1.value % table2.value}
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 5
local anotherTable = {value = 5}
-- perform mod operation between the two tables
local result = myTable % anotherTable
-- print the result
print(result.value)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__Pancada

Essa função é chamada quando um valor é elevado à potência de outro usando o operador ^ .

Vamos entender o metamétodo __pow usando um exemplo:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with a __pow metamethod
local myMetatable = {
__pow = function(table1, table2)
return {value = table1.value ^ table2.value}
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 5
local anotherTable = {value = 5}
-- perform exponentiation operation between the two tables
local result = myTable ^ anotherTable
-- print the result
print(result.value)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__unm

Essa função é invocada quando um valor é negado usando o operador – .

Agora vamos explorar o metamétodo __unm usando um exemplo:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
local myTable = {value = 20}
-- define a metatable with a __unm metamethod
local myMetatable = {
__unm = function(table1, table2)
return {value = -table1.value}
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- perform unary minus operation on table1
local result = -myTable
-- print the result
print(result.value)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__eq

Acionado quando dois valores são comparados usando o operador == .

O exemplo abaixo explica melhor o metamétodo __eq em Lua:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with an __eq metamethod
local myMetatable = {
__eq = function(table1, table2)
return table1.value == table2.value
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 20
local anotherTable = {value = 20}
-- Equality comparison between the two tables
local result = myTable == anotherTable
-- print the result
print(result)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__lt

Executado quando dois valores são comparados usando o operador < .

Usando este exemplo, o metamétodo __lt em Lua é implementado:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with a __lt metamethod
local myMetatable = {
__lt = function(table1, table2)
return table1.value < table2.value
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 30
local anotherTable = {value = 30}
-- Less than comparison between tables
local result = myTable < anotherTable
-- print the result
print(result)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__le

Quando dois valores são comparados usando o operador <= , esta função é chamada.

Este exemplo é usado para examinar o metamétodo __le em Lua:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
local myTable = {value = 20}
-- define a metatable with an __le metamethod
local myMetatable = {
__le = function(table1, table2)
return table1.value <= table2.value
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- define another table with a value of 25
local anotherTable = {value = 25}
-- Less than or equal to comparison between tables
local result = myTable <= anotherTable
-- print the result
print(result)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

__chamar

Este método é invocado quando uma tabela é chamada como uma função.
O exemplo abaixo utiliza o metamétodo __call em Lua:

Example: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- create a table
local myTable = {}
-- define a metatable for myTable with an __call metamethod
local myMetatable = {
__call = function(name)
local str = "Hello John"
return str
end
}
-- set the metatable of myTable to myMetatable
setmetatable(myTable, myMetatable)
-- call myTable as a function
local result = myTable()
-- print the result
print(result) -- should print "Hello John" to the console
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Benefícios das Metatabelas Lua

Lua Metatables oferece vários benefícios, incluindo:

  • As metatabelas permitem personalizar o comportamento das tabelas em Lua. Isso pode ser usado para implementar vários paradigmas de programação, como programação orientada a objetos, ou para adicionar funcionalidade personalizada às tabelas.
  • Ao definir metatabelas, você pode reutilizar o mesmo código em várias tabelas, em vez de escrever o mesmo código repetidamente.
  • As metatabelas Lua permitem estender a funcionalidade dos tipos integrados de Lua, como tabelas e números. Isso pode ser útil ao trabalhar com estruturas de dados complexas ou ao implementar funcionalidades específicas de domínio.
  • As metatabelas Lua podem ser usadas para fornecer uma camada de segurança para programas Lua, impedindo o acesso a certos métodos ou propriedades de tabelas.
  • As metatabelas Lua podem ser usadas para otimizar o desempenho de programas Lua, fornecendo implementações personalizadas de operações comuns, como indexação e operações aritméticas.
Nós valorizamos o seu feedback.
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0
+1
0

Assine a nossa newsletter
Digite seu e-mail para receber um resumo semanal de nossos melhores posts. Saber mais!
ícone