Учебники

Lua — Metatables

Метатабельная таблица — это таблица, которая помогает изменить поведение таблицы, к которой она присоединена, с помощью набора ключей и связанных мета-методов. Эти мета-методы являются мощной функциональностью Lua, которая включает такие функции, как —

  • Изменение / добавление функций к операторам на таблицах.

  • Поиск метатаблиц, когда ключ недоступен в таблице, с помощью __index в метатаблице.

Изменение / добавление функций к операторам на таблицах.

Поиск метатаблиц, когда ключ недоступен в таблице, с помощью __index в метатаблице.

Есть два важных метода, которые используются в обработке метатаблиц, которые включают в себя:

  • setmetatable (table, metatable) — этот метод используется для установки метатаблицы для таблицы.

  • getmetatable (table) — этот метод используется для получения метатаблицы таблицы.

setmetatable (table, metatable) — этот метод используется для установки метатаблицы для таблицы.

getmetatable (table) — этот метод используется для получения метатаблицы таблицы.

Давайте сначала посмотрим, как установить одну таблицу как метатабельную к другой. Это показано ниже.

mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)

Приведенный выше код может быть представлен в одной строке, как показано ниже.

mytable = setmetatable({},{})

_индекс

Простой пример метатаблицы для поиска мета-таблицы, когда она недоступна в таблице, показан ниже.

Live Demo

mytable = setmetatable({key1 = "value1"}, {
   __index = function(mytable, key)
	
      if key == "key2" then
         return "metatablevalue"
      else
         return mytable[key]
      end
   end
})

print(mytable.key1,mytable.key2)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

value1 metatablevalue

Давайте объясним, что произошло в приведенном выше примере, по шагам.

  • Таблица mytable здесь {key1 = «value1»} .

  • Metatable устанавливается для mytable, который содержит функцию для __index, которую мы называем метаметодом.

  • Метаметод выполняет простую работу по поиску индекса «key2», если он найден, он возвращает «metatablevalue», в противном случае возвращает значение mytable для соответствующего индекса.

Таблица mytable здесь {key1 = «value1»} .

Metatable устанавливается для mytable, который содержит функцию для __index, которую мы называем метаметодом.

Метаметод выполняет простую работу по поиску индекса «key2», если он найден, он возвращает «metatablevalue», в противном случае возвращает значение mytable для соответствующего индекса.

У нас может быть упрощенная версия вышеуказанной программы, как показано ниже.

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

__newindex

Когда мы добавляем __newindex в metatable, если ключи не доступны в таблице, поведение новых ключей будет определяться мета-методами. Простой пример, когда индекс метатаблицы устанавливается, когда индекс не доступен в основной таблице, приведен ниже.

Live Demo

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "new  value 1"
print(mytable.key1,mymetatable.newkey1)

Когда вы запускаете вышеуказанную программу, вы получаете следующий вывод.

value1
nil	new value 2
new  value 1	nil

Вы можете видеть в приведенной выше программе, если ключ существует в основной таблице, он просто обновляет его. Когда ключ недоступен в maintable, он добавляет этот ключ в метатаблицу.

Другой пример, который обновляет ту же таблицу с помощью функции rawset, показан ниже.

Live Demo

mytable = setmetatable({key1 = "value1"}, {

   __newindex = function(mytable, key, value)
      rawset(mytable, key, "\""..value.."\"")
   end
})

mytable.key1 = "new value"
mytable.key2 = 4

print(mytable.key1,mytable.key2)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

new value	"4"

rawset устанавливает значение без использования __newindex для metatable. Точно так же есть rawget, который получает значение без использования __index.

Добавление поведения оператора в таблицы

Простой пример объединения двух таблиц с помощью оператора + показан ниже —

Live Demo

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

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

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

Ключ __add включен в metatable для добавления поведения оператора +. Таблица ключей и соответствующего оператора показана ниже.

Sr.No. Режим и описание
1

__добавлять

Изменяет поведение оператора ‘+’.

2

__sub

Изменяет поведение оператора ‘-‘.

3

__mul

Изменяет поведение оператора ‘*’.

4

__div

Изменяет поведение оператора ‘/’.

5

__mod

Изменяет поведение оператора «%».

6

__unm

Изменяет поведение оператора ‘-‘.

7

__concat

Изменяет поведение оператора ‘..’.

8

__eq

Изменяет поведение оператора ‘==’.

9

__lt

Изменяет поведение оператора ‘<‘.

10

__le

Изменяет поведение оператора ‘<=’.

__добавлять

Изменяет поведение оператора ‘+’.

__sub

Изменяет поведение оператора ‘-‘.

__mul

Изменяет поведение оператора ‘*’.

__div

Изменяет поведение оператора ‘/’.

__mod

Изменяет поведение оператора «%».

__unm

Изменяет поведение оператора ‘-‘.

__concat

Изменяет поведение оператора ‘..’.

__eq

Изменяет поведение оператора ‘==’.

__lt

Изменяет поведение оператора ‘<‘.

__le

Изменяет поведение оператора ‘<=’.

__вызов

Добавление поведения вызова метода выполняется с помощью оператора __call. Простой пример, который возвращает сумму значений в основной таблице с переданной таблицей.

Live Demo

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))

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

70

__нанизывать

Чтобы изменить поведение оператора print, мы можем использовать метаметод __tostring. Простой пример показан ниже.

Live Demo

mytable = setmetatable({ 10, 20, 30 }, {
   __tostring = function(mytable)
   sum = 0
	
      for k, v in pairs(mytable) do
         sum = sum + v
      end
		
      return "The sum of values in the table is " .. sum
   end
})
print(mytable)

Когда мы запустим вышеуказанную программу, мы получим следующий вывод.

The sum of values in the table is 60

Если вы полностью знакомы с возможностями мета-таблицы, вы действительно можете выполнить множество операций, которые были бы очень сложными без ее использования. Поэтому постарайтесь больше работать над использованием метатаблиц с различными опциями, доступными в мета таблицах, как описано в примерах, а также создавайте свои собственные образцы.