Арифметические метаметоды. Часть 2
Часть раздела Logic & Flow путешествия по Lua на Coddy — урок 22 из 54.
Основываясь на сложении и вычитании, вы также можете определить поведение умножения и деления для ваших таблиц, используя метаметоды __mul и __div. Они работают так же, как __add и __sub, но реагируют на операторы * и /.
Метаметод __mul особенно полезен, когда вам нужно масштабировать значения таблицы. Например, умножение вектора на число (называемое скаляром) должно приводить к умножению каждого компонента:
local vector = {x = 3, y = 4}
local meta = {
__mul = function(a, b)
local scalar = type(a) == "number" and a or b
local vec = type(a) == "table" and a or b
return {x = vec.x * scalar, y = vec.y * scalar}
end
}
setmetatable(vector, meta)
local scaled = vector * 2
print(scaled.x, scaled.y) -- Результат: 6 8Обратите внимание, как функция проверяет, какой операнд является числом, а какой — таблицей. Это позволяет и vector * 2, и 2 * vector работать корректно.
Метаметод __div работает аналогично для деления:
local meta = {
__div = function(a, b)
return {x = a.x / b, y = a.y / b}
end
}
setmetatable(vector, meta)
local divided = vector / 2
print(divided.x, divided.y) -- Вывод: 1.5 2Эти метаметоды дополняют базовые арифметические операции для ваших пользовательских типов, предоставляя вам полный контроль над тем, как математические операторы ведут себя с вашими таблицами.
Задание
ЛегкоНапишите функцию scaleVector, которая принимает x, y и scalar и возвращает масштабированный вектор в виде отформатированной строки.
Создайте таблицу вектора с заданными координатами, прикрепите метатаблицу с метаметодом __mul для включения умножения на скаляр, умножьте вектор на скаляр с помощью оператора * и верните результат.
Логика:
- Создайте таблицу вектора с ключами
xиy, установленными в соответствии с предоставленными координатами - Создайте метатаблицу с
__mul, которая обрабатывает умножение вектора на скаляр - Функция
__mulдолжна проверять, какой операнд является числом, а какой — таблицей - Верните новую таблицу с
x = vec.x * scalarиy = vec.y * scalar - Прикрепите метатаблицу к таблице вектора с помощью
setmetatable() - Умножьте вектор на скаляр, используя
vector * scalar - Верните результат в виде строки в формате
"x y"(значения x и y, разделенные пробелом)
Параметры:
x(number): Координата x вектораy(number): Координата y вектораscalar(number): Скалярное значение, на которое нужно умножить вектор
Возвращает: Масштабированный вектор в виде строки в формате "x y" (string)
Шпаргалка
Метаметоды __mul и __div определяют поведение умножения и деления для таблиц, реагируя на операторы * и /.
Метаметод __mul полезен для масштабирования значений таблицы. При умножении вектора на скаляр проверьте, какой операнд является числом, а какой — таблицей, чтобы разрешить использование как vector * 2, так и 2 * vector:
local vector = {x = 3, y = 4}
local meta = {
__mul = function(a, b)
local scalar = type(a) == "number" and a or b
local vec = type(a) == "table" and a or b
return {x = vec.x * scalar, y = vec.y * scalar}
end
}
setmetatable(vector, meta)
local scaled = vector * 2
print(scaled.x, scaled.y) -- Вывод: 6 8Метаметод __div работает аналогично для деления:
local meta = {
__div = function(a, b)
return {x = a.x / b, y = a.y / b}
end
}
setmetatable(vector, meta)
local divided = vector / 2
print(divided.x, divided.y) -- Вывод: 1.5 2Попробуйте сами
function scaleVector(x, y, scalar)
-- Напишите код здесь
end
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Logic & Flow
1Продвинутая итерация таблиц
Итерация с помощью pairs()Итерация с помощью ipairs()pairs() против ipairs()Повторение — Лист персонажа4Введение в метатаблицы
Что такое метатаблица?setmetatable и getmetatableМетаметод __indexМетаметод __newindexМетаметод __tostringАрифметические метаметоды. Часть 1Арифметические метаметоды. Часть 2Итоги — Таблица только для чтения2Дополнительные функции библиотеки table
table.concat()Создание таблиц и unpack()table.sort()Пользовательская сортировка с помощью функцийИтоги — Таблица рекордов