Ваш код не содержит "заполненных таблиц" для возврата.
Ваша функция newPlayer
создает таблицу и возвращает ее. Он создает ряд функций в этой таблице. Но это все, что делает newPlayer
: создает таблицу и помещает в нее некоторые функции.
Данные , к которым получают доступ эти функции, не являются частью таблицы. n
, h
, a
и r
(кстати, используйте более подходящие имена переменных) - все это локальные переменные. Ваши внутренние функции будут обращаться к указанному c стеку, содержащему эти переменные, но сами переменные не будут магически связаны с таблицей.
Ваша принципиальная проблема почти наверняка связана с установщиками. И это происходит из комбинации этого:
function player:setPlayerName(arg)
с этим:
player1.getPlayerName()
Когда вы создаете функцию, используя символ :
между именем таблицы и именем функции, Вы используете syntacti c sugar для функции, которая неявно принимает в качестве первого аргумента значение, называемое self
. Как следует из названия, это должно представлять объект, к которому эта функция вызывается. Таким образом, код создания вашей функции эквивалентен:
function player.setPlayerName(self, arg)
Поскольку вы создаете все свои функции с помощью :
, все ваши функции принимают хотя бы один параметр.
:
синтаксис также может использоваться при вызове таких функций. Если вы сделали player1:getPlayerName()
, это приведет к тому, что в таблице, к которой вы обратились, будет найдена функция getPlayerName
, которая будет использоваться в качестве первого аргумента в вызове функции. Таким образом, эта строка будет эквивалентна player1.getPlayerName(player1)
.
Очевидно, что эти два синтаксиса являются зеркалами друг друга: функции, созданные с помощью :
, принимают параметр, который, как ожидается, ссылается на таблицу, для которой вызывается и функции, вызываемые с помощью :
, будут с учетом таблицы, к которой обращались для получения этой функции.
Но ... ваш код не придерживался симметрии. Вы создали функции с помощью :
, но вы вызываете их с помощью .
Теперь вам, get
функциям, это сойдет с рук, потому что ... ну, нет ваши значения на самом деле часть таблицы . Таким образом, ваши get
функции просто возвращают локальное значение, которое они приняли из своего контекста создания.
Функции set
представляют проблему. Видите, они принимают параметр. Но поскольку функция была объявлена с :
, они действительно принимают два параметра , первый из которых неявный self
.
Теперь синтаксис :
- это просто syntacti c сахар; это просто удобный способ сделать то, что вы могли бы сделать сами. Так что теоретически нормально вызывать функцию с .
, даже если вы создали ее с :
. Но если вы сделаете это, вы должны передать таблицу в качестве первого параметра. Хотя ваш код этого не показывает, я сильно подозреваю, что вы этого не сделали.
Если вы вызвали player1.setPlayerName("foo")
, то получится, что неявный параметр self
получит значение "foo"
и параметр arg
будет nil
. И вы назначите это значение nil
локальной переменной n
. Поэтому последующие вызовы player1.getPlayerName()
вернут nil
.
По сути, здесь происходит то, что вы комбинируете два разных способа создания объектов в Lua. Вы хранили свои личные данные так, что внешний код не мог получить к ним доступ (ie: локальные значения), но теперь эти данные больше не являются частью самой таблицы . Это означает, что, хотя вы покорно создаете эти функции с синтаксисом :
, чтобы указать, что они принимают таблицу self
, они на самом деле не используют эту таблицу . И поскольку они никогда не используют таблицу, гораздо сложнее выяснить, что происходит не так.
По сути, здесь ключ к симметричности. Если вы создаете функцию с :
, то вам следует либо вызвать ее с :
, либо обязательно передать ей таблицу объектов в качестве первого параметра.
В общем, стандартный способ Создавать приватных членов можно условно, а не запретив это. То есть вы соглашаетесь не связываться ни с кем за столом, кроме как с определенными именами. Соглашение Python состоит в том, чтобы притворяться, что имена, начинающиеся с _
, не существуют, и программы Lua иногда используют это.
Значения апгрейда - интересное решение для частных переменных, но они имеют проблемы. Если вы хотите изобрести переменную-член, вы должны делать это в централизованном месте, а не там, где вам это может понадобиться. Даже если переменная является необязательной, вы должны создать имя local
в верхней части функции.