English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Lua 元表(Metatable)

Dans Lua table, nous pouvons accéder aux clés pour obtenir des valeurs, mais nous ne pouvons pas opérer sur deux tables.

Par conséquent, Lua fournit des métatables, permettant de changer le comportement des tables, chaque comportement étant associé à une méthode métier.

Par exemple, en utilisant un métatable, nous pouvons définir comment Lua calcule la somme de deux tables a+b。

Lorsque Lua essaie de sommer deux tables, il vérifie d'abord si l'une des deux a un métatable, puis s'il existe un champ appelé "__add", s'il le trouve, il appelle la valeur correspondante. Les champs "__add" et autres sont des champs immuables, et leurs valeurs (souvent une fonction ou une table) sont des "méthodes métier".

Il y a deux fonctions très importantes pour gérer les métatables :

  • setmetatable(table,metatable): Définir un métatable pour une table spécifique, si le métatable contient une clé __metatable, setmetatable échoue.

  • getmetatable(table): Renvoie le métatable de l'objet.

Le prochain exemple montre comment définir un métatable pour une table spécifique :

mytable = {}                          -- Table standard 
mymetatable = {}                      -- Métatable
setmetatable(mytable,mymetatable)     -- Définir mymetatable comme métatable de mytable

Le code ci-dessus peut également être écrit en une ligne :

mytable = setmetatable({},{})

Voici l'objet métier renvoyé :

getmetatable(mytable)                 -- Cela renvoie mymetatable

__index Méthode métier

C'est la clé la plus couramment utilisée dans le metatable.

Lorsque vous accédez à une table par une clé, si cette clé n'a pas de valeur, Lua cherche alors la clé __index dans le metatable de cette table (si un metatable existe). Si __index contient une table, Lua cherche la clé correspondante dans cette table.

Nous pouvons utiliser la commande lua pour entrer en mode interactif et voir :

$ lua
Lua 5.3.0  Copyright (C) 1994-2015 Lua.org, PUC-Rio
> other = { foo = 3 } 
> t = setmetatable({}, { __index = other }) 
> t.foo
3
> t.bar
nil

Si __index contient une fonction, Lua appelle cette fonction et la table ainsi que la clé sont passées en paramètres à la fonction.

__index Méthode méta vérifie si l'élément de la table existe, s'il n'existe pas, retourne nil ; s'il existe, le résultat est retourné par __index.

mytable = setmetatable({key1 = "valeur"1"}, {
  __index = function(mytable, key)
    if key == "key2" then
      return "metatablevalue"
    else
      return nil
    end
  end
)
print(mytable.key1,mytable.key2)

Le résultat de la sortie de l'exemple est :

1    metatablevalue

Analyse de l'exemple :

  • mytable table assignée à {key1 = "value1"}.

  • mytable a configuré une méthode méta, la méthode méta est __index.

  • Recherchez key dans mytable1Si vous trouvez, retournez cet élément, sinon continuez.

  • Recherchez key dans mytable2Si vous trouvez, retournez metatablevalue, sinon continuez.

  • Vérifiez si la méthode méta __index existe, si __index est une fonction, appelez cette fonction.

  • Recherchez dans la méthode méta s'il y a un "key2" clé des paramètres (mytable.key2Déjà configuré), si vous entrez "key2" Paramètre de retour "metatablevalue", sinon retourne la valeur associée à la clé de mytable .

Nous pouvons simplifier le code suivant :

mytable = setmetatable({key1 = "valeur"1"}, { __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)

Résumé

Les règles de Lua pour trouver un élément d'une table sont en réalité les suivantes 3 Étapes :

  • 1.Recherchez dans la table, si vous trouvez, retournez cet élément, sinon continuez.

  • 2.Vérifiez si la table a une méthode méta, si elle n'en a pas, retourne nil, sinon continue.

  • 3.Vérifiez si la méthode méta __index existe, si __index est nil, retourne nil ; si __index est une table, répète 1、2、3;si la méthode __index est une fonction, retourne la valeur de retour de cette fonction.

Cette partie de contenu provient de l'auteur Huanzi : https://blog.csdn.net/xocoder/article/details/9028347

Méthode méta __newindex

La méthode méta __newindex est utilisée pour mettre à jour la table, tandis que __index est utilisé pour accéder à la table .

Lorsque vous assignez une valeur à un index manquant d'une table, l'interpréteur recherche la méthode méta __newindex : s'il existe, cette fonction est appelée sans effectuer l'assignment.

L'exemple suivant montre l'utilisation de la méthode méta __newindex :

mymetatable = {}
mytable = setmetatable({key1 = "valeur"1"}, { __newindex = mymetatable })
print(mytable.key1)
mytable.newkey = "新值2"
print(mytable.newkey,mymetatable.newkey)
mytable.key1 = "新值1"
print(mytable.key1,mymetatable.key1)

Le résultat de l'exécution de l'exemple ci-dessus est :

1
2
nouvelle valeur1    nil

Dans l'exemple ci-dessus, la table a définie la méthode métier __newindex, lors de l'affectation à un nouveau clé d'index (mytable.newkey = "nouvelle valeur2) appellera la méthode métier, sans effectuer d'affectation. Et si vous affectez à un index clé existant (key1) entraînera une affectation, sans appeler la méthode métier __newindex.

Voici un exemple utilisant la fonction rawset pour mettre à jour la table :

mytable = setmetatable({key1 = "valeur"1"}, {
  __newindex = function(mytable, key, value)
                rawset(mytable, key, \
  end
)
mytable.key1 = "nouvelle valeur"
mytable.key2 = 4
print(mytable.key1,mytable.key2)

Le résultat de l'exécution de l'exemple ci-dessus est :

nouvelle valeur		"4"

Ajouter des opérateurs à la table

Voici un exemple démontrant l'opération d'addition de deux tables :

-- Calculer la valeur maximale du tableau, table.maxn en Lua5.2Il est impossible d'utiliser cette version
-- Fonction personnalisée de calcul de la valeur maximale du tableau, table.maxn, qui calcule le nombre d'éléments du tableau
function table_maxn(t)
    local mn = 0
    for k, v in pairs(t) do
        if mn < k then
            mn = k
        end
    end
    return mn
end
-- Opération d'addition de deux tables
mytable = setmetatable({ 1, 2, 3 }, {
  __add = function(mytable, newtable)
    for i = 1, table_maxn(newtable) do
      table.insert(mytable, table_maxn(mytable)+1,newtable[i])
    end
    return mytable
  end
)
secondtable = {4,5,6}
mytable = mytable + secondtable
        for k,v in ipairs(mytable) do
print(k,v)
end

Le résultat de l'exécution de l'exemple ci-dessus est :

1    1
2    2
3    3
4    4
5    5
6    6

__add clé incluse dans la table métier, et effectue l'opération d'addition. La liste des opérations correspondantes dans la table est la suivante : (Attention :__est deux underscores)

modedescription
__addl'opérateur correspondant '+'.
__subl'opérateur correspondant '-'.
__mull'opérateur correspondant '*'.
__divl'opérateur correspondant '/'.
__modl'opérateur correspondant '%'.
__unml'opérateur correspondant '-'.
__concatl'opérateur correspondant '..'.
__eql'opérateur correspondant '=='.
__ltl'opérateur correspondant '<'.
__lel'opérateur correspondant '<='.

__call méthode métier

__call méthode métier est appelée lors de l'appel d'une valeur en Lua. Voici un exemple démontrant la somme des éléments d'une table :

-- Calculer la valeur maximale du tableau, table.maxn en Lua5.2Il est impossible d'utiliser cette version
-- Fonction personnalisée de calcul de la valeur maximale du tableau, table.maxn, qui calcule le nombre d'éléments du tableau
function table_maxn(t)
    local mn = 0
    for k, v in pairs(t) do
        if mn < k then
            mn = k
        end
    end
    return mn
end
-- Définir la méthode méta __call
mytable = setmetatable({10}, {
  __call = function(mytable, newtable)
        sum = 0
        for i = 1, table_maxn(mytable) do
                sum = sum + mytable[i]
        end
    for i = 1, table_maxn(newtable) do
                sum = sum + newtable[i]
        end
        return sum
  end
)
newtable = {10,20,30}
print(mytable(newtable))

Le résultat de l'exécution de l'exemple ci-dessus est :

70

Méthode méta __tostring

La méthode méta __tostring est utilisée pour modifier le comportement de sortie du tableau. Dans l'exemple suivant, nous avons personnalisé le contenu de sortie du tableau :

mytable = setmetatable({ 10, 20, 30 }, {
  __tostring = function(mytable)
    sum = 0
    for k, v in pairs(mytable) do
                sum = sum + v
        end
    return "La somme de tous les éléments du tableau est" .. sum
  end
)
print(mytable)

Le résultat de l'exécution de l'exemple ci-dessus est :

La somme de tous les éléments du tableau est 60

De ce, comprendre les méta-tables de Lua peut nous aider à écrire des codes Lua plus simples et excellents.