Menu
Coddy logo textTech

Арифметические метаметоды. Часть 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

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

challenge icon

Задание

Легко

Напишите функцию 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
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Logic & Flow