×

Langue

Fermer
Atelier 801
  • Forums
  • Dev Tracker
  • Connexion
    • English Français
      Português do Brasil Español
      Türkçe Polski
      Magyar Română
      العربية Skandinavisk
      Nederlands Deutsch
      Bahasa Indonesia Русский
      中文 Filipino
      Lietuvių kalba 日本語
      Suomi עברית
      Italiano Česky
      Hrvatski Slovensky
      Български Latviešu
      Estonian
  • Langue
  • Forums
  • /
  • Transformice
  • /
  • Modules
  • /
  • [Tutorial] Metatables & Metamétodos
[Tutorial] Metatables & Metamétodos
Bolodefchoco
« Sénateur »
1515098400000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#1
  2

Metatables & Metamétodos
Recriado


 Em lua, há diferentes tipos de meta métodos. Eles realizam funções dentro de uma tabela, e essa tabela que contém um metamethod é chamada de metatable.

 "Essa meta tabela é uma tabela Lua comum que define o comportamento do valor original sob certas operações especiais. Você pode mudar vários aspectos do comportamento de operações sobre um valor especificando campos específicos em sua meta tabela.", (manual lua)

 Cada meta método é precedido por dois underscores ( _ ) e o nome do event, como em __event
.

Sumário de funções:
» getmetatable(tabela)
    - Caso a tabela de argumento seja uma metatable, esta função retornará todos os metamethods dessa tabela, exceto no instante que existir um meta método chamado __metatable, que apenas ela será retornada.
» setmetatable(tabela, metatabela)
    - Estabelece o(s) (novo(s)) meta método(s) da/na tabela inserida, mas caso o argumento metatabela seja nil, o(s) meta método(s) da tabela inserida será(ão) removido(s), caso exista o meta método __metatable na tabela original inserida (caso não seja o primeiro meta método ou a tabela já seja metatable), um erro será retornado.
Sumário de metamethods:
__index(list,index)
    - É executado quando o índice de uma tabela é chamado. Seus argumentos são list (tabela) e index (nome da variável)
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    garbage = setmetatable({},{
    __index = function(list,index)
    return "Not Nil! Biiiirl! The monster!!!!!"
    end
    })

    garbage.Tig = 1
    garbage.Noob = 2

    print(garbage["Tig Noob"])
    print(garbage.Tig)
    print(garbage["Noob"])
     
__newindex(list,index,value)
    - É executado quando um índice dentro da tabela é criado. Seus argumentos são list (tabela), index (nome da variável) e value (valor da nova variável)
    Exemplo
    Code Lua

    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
    calc = setmetatable({},{
    __newindex = function(list,index,value)
    if type(value[1]) == "number" and type(value[2]) == "number" then
    local math = {
    [1] = value[1],
    [2] = value[2],
    add = value[1] + value[2],
    sub = value[1] - value[2],
    mul = value[1] * value[2],
    div = value[1] / value[2],
    }
    rawset(list,index,math)
    else
    rawset(list,index,value)
    end
    end
    })

    calc.cake = {10,20}

    print(calc.cake[1])
    print(calc.cake[2])
    print(calc.cake.add)
    print(calc.cake.sub)
    print(calc.cake.mul)
    print(calc.cake.div)
     
__call(list,arg)
    - É executado quando uma tabela é chamada como função. Seus argumentos são list (tabela) e arg (argumento(s) passados pela suposta "função") (também pode ser representado por ...)
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    local call = {
    __call = function(list,arg)
    print(("[%s [%dy]] %s!"):format(arg.name,arg.age,arg.quote))
    end
    }

    humanProfile = setmetatable({},{
    __newindex = function(list,index,value)
    rawset(list,index,setmetatable(value,call))
    end
    })

    humanProfile[1] = {
    name = "Homer Simpson",
    age = 40,
    quote = "I am sorry, God, but I do not trust you!",
    }


    humanProfile[1](humanProfile[1])
     
__concat(...)
    - É executado quando ocorre uma concatenação de valores diferentes (ex: a tabela com uma string). Seu argumento é ..., onde são passados todos os valores que foram concatenados. (Também representado como o1, o2)
    Exemplo
    Code Lua

    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
    30
    31
    32
    33
    local concat = {
    __concat = function(...)
    local values = {}
    local args = {...}
    for i = 1,#args do
    if type(args[i]) == "table" then
    for k,v in next,args[i] do
    values[#values + 1] = v
    end
    else
    values[#values + 1] = args[i]
    end
    end
    return table.concat(values,", ")
    end
    }

    list = setmetatable({},{
    concat,
    __newindex = function(list,index,value)
    if type(value) == "table" then
    rawset(list,index,setmetatable(value,concat))
    else
    rawset(list,index,value)
    end
    end
    })

    list.food = "pasta"
    list.soda = {"coke","grape"}
    list.trolls = {"Tigrounette","Pikashu"}

    print(list.soda .. list.trolls .. list.food)
     
__add(n1,n2)
    - É executado quando ocorre uma adição entre valores não numéricos (ou um numérico e outro não). Seus argumentos são n1 e n2, os dois "números" ou "valores" que estão sendo somados.
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __add = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 + n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath + sMath + 2)
     
__sub(n1,n2)
    - É executado quando ocorre uma subtração entre valores não numéricos (ou um numérico e outro não). Seus argumentos são n1 e n2, os dois "números" ou "valores" que estão sendo subtraídos.
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __sub = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 - n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath - 3)
     
__mul(n1,n2)
    - É executado quando ocorre uma multiplicação entre valores não numéricos (ou um numérico e outro não). Seus argumentos são n1 e n2, os dois "números" ou "valores" que estão sendo multiplicados.
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __mul = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 * n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath * 4)
     
__div(n1,n2)
    - É executado quando ocorre uma divisão entre valores não numéricos (ou um numérico e outro não). Seus argumentos são n1 e n2, os dois "números" ou "valores" que estão sendo divididos.
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __div = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 / n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath / 4)
     
__pow(n1,n2)
    - É executado quando ocorre uma exponenciação (1²) entre valores não numéricos (ou um numérico e outro não). Seus argumentos são n1 e n2, os dois "números" ou "valores" que estão sendo exponenciados.
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __pow = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 ^ n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath ^ 2)
     
__mod(n1,n2)
    - É executado quando ocorre um mod (1%2 (Coletar o resto da divisão entre 2 números)) entre valores não numéricos (ou um numérico e outro não). Seus argumentos são n1 e n2, os dois "números" ou "valores" que estão sendo "modularizados".
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __mod = function(n1,n2)
    n1,n2 = (type(n1) == "table" and #n1 or n1),(type(n2) == "table" and #n2 or n2)
    return n1 % n2
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(sMath % 3)
     
__unm(n1)
    - É executado quando ocorre um valor não numérico é chamado com unário (no caso, seria o mesmo que chamar "-var" para que o número de var seja negativo). Seu argumento é o n1, o "número" ou "valor" que está sendo transformado num número negativo.
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    sMath = setmetatable({},{
    __unm = function(n1)
    n1 = (type(n1) == "table" and #n1 or n1)
    return -n1
    end
    })

    sMath[1] = 0
    sMath[2] = 0
    sMath[3] = 0
    sMath[4] = 0

    print(-sMath)
     
__metatable()
    - Bloqueia a função getmetatable de coletar o meta método real da tabela inserida, e, ao invés dela, acaba mandando o metamethod __metatable como forma de proteção.
    Exemplo
    Code Lua

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    str = setmetatable({},{
    __metatable = "Nothing here, noob!",
    __newindex = function(list,key,value)
    print(key .. " Biirl!")
    rawset(list,key,value)
    end
    })

    print(getmetatable(str))
    print(getmetatable(str).__newindex)

    str.test = '?'

    tbl = setmetatable({},{
    __newindex = function(list,key,value)
    print(key .. " Huuuu!")
    rawset(list,key,value)
    end
    })

    print(getmetatable(tbl))
    print(getmetatable(tbl).__newindex)

    tbl.test = '?'
     

Dernière modification le 1517428140000
Breno
« Citoyen »
1515099060000
    • Breno#0544
    • Profil
    • Derniers messages
#2
  0
ta [size=0]kkkkkkk
Bolodefchoco
« Sénateur »
1515099240000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#3
  0
Ffulanoss a dit :
ta [size=0]kkkkkkk

Desculpe. Melhorou?
Breno
1515099420000
    • Breno#0544
    • Profil
    • Derniers messages
#4
[Modéré par Kiwrimai, raison : Comentário sem relação com o tópico.]
Mescouleur
« Citoyen »
1517430180000
    • Mescouleur#0000
    • Profil
    • Derniers messages
#5
  0
Parece ser útil
Bolodefchoco
« Sénateur »
1517430240000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#6
  0
Mescouleur a dit :
Parece ser útil

E são! Uso bastante hehe
Mescouleur
« Citoyen »
1517436360000
    • Mescouleur#0000
    • Profil
    • Derniers messages
#7
  0
Bolodefchoco a dit :
Mescouleur a dit :
Parece ser útil

E são! Uso bastante hehe

basiquez é o meu mundo
Jp_darkuss
« Citoyen »
1579909620000
    • Jp_darkuss#4806
    • Profil
    • Derniers messages
#8
  0
Eu achava que isto era bem difícil, mas é bem fácil, parabéns Bolo. Mas tenho uma dúvida, mesmo tendo um metamétodo, a tabela pode ainda armazenar um valor comum? Pois já tentei usar o valor de uma metatabela e retornou nil '-'
Bolodefchoco
« Sénateur »
1580066280000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#9
  0
Jp_darkuss a dit :
Eu achava que isto era bem difícil, mas é bem fácil, parabéns Bolo. Mas tenho uma dúvida, mesmo tendo um metamétodo, a tabela pode ainda armazenar um valor comum? Pois já tentei usar o valor de uma metatabela e retornou nil '-'

Não entendi sua pergunta. Manda um exemplo aí
Jp_darkuss
« Citoyen »
1580134980000
    • Jp_darkuss#4806
    • Profil
    • Derniers messages
#10
  0
Bolodefchoco a dit :
Jp_darkuss a dit :
Eu achava que isto era bem difícil, mas é bem fácil, parabéns Bolo. Mas tenho uma dúvida, mesmo tendo um metamétodo, a tabela pode ainda armazenar um valor comum? Pois já tentei usar o valor de uma metatabela e retornou nil '-'

Não entendi sua pergunta. Manda um exemplo aí

Assim, digamos que:

Code Lua

1
2
3
4
5
6
7
8
9
10
11
local tabela= setmetatable({}, {
__newindex= function(tabela, index, value)
print(value)
end
})
tabela[1]= 4
print(tabela[1])

> 4 -- valor retornado pela função __newindex
> nil -- valor retornado pelo print
--Neste exemplo a metatabela "tabela" recebeu o metamétodo "__newindex", que em um de seus argumentos retorna um novo valor. Porém certa vez tentei usar o valor que a tabela recebeu, e retornou nil. Por exemplo se eu fizesse tabela[1] + 2 não ia dar certo por que segundo Lua não existe valor nesta tabela, sendo que eu dei um valor, 4.

Entendeu?
É como se o valor em tabela[1] nem existisse ' -'

Dernière modification le 1580135040000
Bolodefchoco
« Sénateur »
1580136000000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#11
  0
É porque seu newindex só printa.. Você precisa utilizar rawset(tabela, index, value) para definir o valor dentro do metametodo. Essa função ignora metametodos da tabela na hora de setar
Jp_darkuss
« Citoyen »
1580162760000
    • Jp_darkuss#4806
    • Profil
    • Derniers messages
#12
  0
Entendi, obg.
Gamedroit
« Citoyen »
1587660960000
    • Gamedroit#3347
    • Profil
    • Derniers messages
    • Tribu
#13
  0
Agora que notei, está faltando os metamethods __len e __tostring

__len, que foi implementado a partir do Lua versão 5.2, permite gerenciar o tamanho de uma metatable por exemplo:
Code Lua

1
2
3
4
5
6
local unknown = {1,2,3}
print(#unknown) -- Naturalmente retorna 3
local garbage = setmetatable(unknown, {
__len = function(self) return 0 end
})
print(#garbage) -- Mesmo sendo uma cópia de Unknown e tendo armazenado 3 valores ele vai retornar 0 pois o operador foi sobrescrito

Já __tostring tem a capacidade de manipular o retorno da função tostring(Valor) e como print desfruta da mesma também consequentemente modifica seu resultado no #lua ao imprimir a tabela modificada, por exemplo:
Code Lua

1
2
3
4
5
6
7
local unknown = {}
print(unknown) -- resultado: "table: address"
local garbage = setmetatable (unknown, {
__tostring = function(self) return "hello world!" end
})
print(garbage) -- resultado: "hello world!"
-- a mesma coisa para tostring(garbage)
Bolodefchoco
« Sénateur »
1587669240000
    • Bolodefchoco#0095
    • Profil
    • Derniers messages
    • Tribu
#14
  0
Este tópico só menciona as metatables que funcionam no Transformice, de contrário seriam inúteis neste fórum.
Gamedroit
« Citoyen »
1587674640000
    • Gamedroit#3347
    • Profil
    • Derniers messages
    • Tribu
#15
  0
Bolodefchoco a dit :
Este tópico só menciona as metatables que funcionam no Transformice, de contrário seriam inúteis neste fórum.

Hm... As que citei não funcionam? Que tristeza o Lua do tfm é pobre mesmo em recursos, não vejo problema em manter as funcionalidades padrões do Lua, a única coisa que a Atelier precisava bloquear seria io e package além da função require

Dernière modification le 1587675180000
  • Forums
  • /
  • Transformice
  • /
  • Modules
  • /
  • [Tutorial] Metatables & Metamétodos
© Atelier801 2018

Equipe Conditions Générales d'Utilisation Politique de Confidentialité Contact

Version 1.27