2015-07-01 2 views
2

В Roblox Studio, у меня есть объект ModuleScript, который реализует аналогичный класс к показанному в главе 16 1-е издание программирования на языке Lua, как показано ниже:Настройка __index текущей среды в Roblox

local h4x0r = { } 

local function setCurrentEnvironment(t, env) 
    if (not getmetatable(t)) then 
     setmetatable(t, { __index = getfenv(0) }) 
    end 

    setfenv(0, t) 
end 

do 
    setCurrentEnvironment(h4x0r); 

    do 
     h4x0r.Account = { }; 
     setCurrentEnvironment(h4x0r.Account); 
     __index = h4x0r.Account; 

     function withdraw(self, v) 
      self.balance = self.balance - v; 
      return self.balance; 
     end 

     function deposit(self, v) 
      self.balance = self.balance + v; 
      return self.balance; 
     end 

     function new() 
      return setmetatable({ balance = 0 }, h4x0r.Account) 
     end 

     setCurrentEnvironment(h4x0r); 
    end 
end 

return h4x0r 

затем я попытался использовать следующий скрипт для доступа к классу Account, при условии, что все члены 2-го до-конца блока будет назначен h4x0r.Account:

h4x0r = require(game.Workspace.h4x0r); 
Account = h4x0r.Account; 

account = Account.new(); 
print(account:withdraw(100)); 

Данный скрипт завершается с ошибкой Workspace.Script:5: attempt to call method 'withdraw' (a nil value), так что это должна быть проблема в отношении l ine, где я установил поле __indexh4x0r.Account.

Может кто-нибудь объяснить мне, где я ошибся?

ответ

1

Попробуйте использовать getfenv(2) и setfenv(2, t) вместо getfenv(0) и setfenv(0, t). Вы по существу хотите изменить окружение обволакивающей функции, которая будет суммироваться 2. Уровень

0 это особый аргумент, который бы вместо того, чтобы получить или установить среду нити, который используется в качестве default environment в некоторых случаях, но это не влияет на отдельные замыкания, которые уже были созданы в потоке, поэтому в этом случае это не работает.