Переопределить функцию экземпляра Lua

Я пытаюсь изменить поведение функции Lua, добавив код в ее начало или конец. Поскольку это мод для игры, я не могу редактировать функцию напрямую, поэтому вместо этого я должен ее переопределить. Я достигаю этого, сохраняя ссылку на исходную функцию в локальной переменной, а затем переопределяя функцию с моей собственной, которая вызывает исходную функцию вместе с любым кодом префикса или постфикса, который мне нужно добавить, например так:

local base_exampleFunction = ExampleBaseGameClass.exampleFunction

function ExampleBaseGameClass.exampleFunction(param1, param2)

    --Prefix code goes here

    base_exampleFunction(param1, param2);

    --Postfix code goes here
    
end

Это прекрасно работает для функций, определенных с синтаксисом ClassName.functionName, но некоторые функции вместо этого используют ClassName:functionName, которые, насколько я понимаю, являются функциями, которые передают ссылку на экземпляр класса в качестве первого параметра. Я не могу понять, как префикс/постфикс этих функций, так как я получаю следующую ошибку при объявлении переменной для хранения исходной функции, если я попробую тот же подход:

attempted index: exampleFunction of non-table: null

Есть ли способ заставить это работать?

3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
1
0
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

: функции — это просто пугающие способы сказать «первый аргумент — self».

Итак, ExampleBaseGameClass:exampleFunction(param2) эквивалентно ExampleBaseGameClass:exampleFunction(ExampleBaseGameClass, param2)! Он просто получил self в начале, и функции, объявленные с :, будут иметь невидимую переменную self, появляющуюся из ниоткуда.

local a = {}
function a.b(self)
    print(self)
end
function a:c()
    print(self)
end

-- a.c(a) == a:c()
-- a:b() == a.b(a)
-- a:b() == a:c()

Используя эту идею, мы можем просто добавить аргумент (он не обязательно должен называться «я», он просто должен быть первым аргументом).

Этот должен работает, если только в вашей среде Lua нет части (например, причудливых метатаблиц), которая предотвратила бы такое:

local base_exampleFunction = ExampleBaseGameClass.exampleFunction

function ExampleBaseGameClass.exampleFunction(self, param1, param2)

    --Prefix code goes here

    base_exampleFunction(self, param1, param2);

    --Postfix code goes here
    
end

Библиотека lua использует преимущество первого аргумента, являющегося вызывающим объектом для ее библиотеки строк. Обратите внимание, как работает ("hello"):gsub() — в качестве первого аргумента передается сама строка!

Ошибка, которую я получаю (попытка index: exampleFunction of non-table: null), происходит прямо в первой строке, где определена локальная переменная, поэтому добавление себя к переопределенной функции не решает проблему, хотя я предполагаю, что это также необходимо, учитывая ваше объяснение. Есть ли что-то, что мне нужно изменить в объявлении локальной переменной?

PM4 22.04.2022 20:20

Вы уверены, что эквивалент ExampleBaseGameClass в вашем сценарии действительно существует? Проверьте на опечатки, так как ошибка подразумевает, что ExampleBaseGameClass не существует, а не exampleFunction.

Mooshua 22.04.2022 20:23

@ PM4, тогда ExampleBaseGameClass имеет значение null в том месте, где вы запускаете этот код. Это не имеет ничего общего с функциями :

user253751 22.04.2022 20:29

Спасибо! Вы оба правы, базовый класс игры инициализируется только в контексте сервера, а не клиента, тогда как мое переопределение выполнялось в обоих контекстах, отсюда и ошибка при запуске клиента.

PM4 22.04.2022 20:45

Другие вопросы по теме