2014-01-23 5 views
0

получил некоторые проблемы с metatable. Это мой простой метатаблица:Подразделение metatable

local mt = {} 
function mt:add(n) 
    return setmetatable({n = n}, {__index = mt}) 
end 

function mt:get() return self.n end 

Теперь я хочу, чтобы добавить некоторые подразделения, как:

mt.math 
mt.effect 

Что каждый из них имеет некоторые собственные методы, как:

mt.math:floor() return math.floor(self:get()) end 
mt.effect:show(args) onMapShowEffect(self:get(), {x = x + (args[1] ~= nil or 0), ...) end 
mt.effect:get() return getCurrentPos() end 

Любые идеи?

ОК, пытаясь сделать все подробности, чтобы поделиться своей проблемой.

Player = {} 
function Player:add(this) 
    return setmetatable({this = this}, {__index = Player}) 
end 

Player:get() return self.this end 

Приведенный выше код работает отлично на этом примере

function enterToGame(player1, player2) 
    local p1 = Player:add(player1) 
    local p2 = Player:add(player2) 
    print(p1:get()) -- ID1 
    print(p2:get()) -- ID2 

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

Player.info = { 
    id = function() return Player:get() end, 
} 
Player.pos = { 
    get = function() return getPosition(Player:get()) end, 
    set = function(args) setPosition(Player:get(), args) end, 
} 
Player.speed = { 
    get = function() return getSpeed(Player:get()) end, 
    set = function(value) setSpeed(value) end, 
    improve = function(value) setSpeed(Player.speed.get() + value) end, 
} 

Но это не работаю именно то, что я хочу:

function enterToGame(player1, player2) 
    local p1 = Player:add(player1) 
    local p2 = Player:add(player2) 
    print(p1:get()) -- ID1 
    print(p2:get()) -- ID2 
    print(p1.info.id()) -- ID2 instead of ID1 
    print(p2.info.id()) -- ID2 

Когда я помещал игрок: получить() в моих методах его возвращение заявления последнего объекта.

+0

Я не уверен, что я точно понимаю вопрос, но 'self' в этих внутренних функциях будет представлять собой таблицы' mt.math'/'mt.effect', а не таблицу' mt' верхнего уровня в случае что вам было непонятно. –

+0

Есть ли способ позвонить в mt? – Synchro

+0

Если вы дадите вашей таблице mt метатет '__call', ее можно вызвать. Я не уверен, насколько это важно для вашего вопроса. –

ответ

0

Основываясь на том, что вы заявляете, если вы

mt.math = mt:add(123) 

Вам не нужно mt:get(), потому что т является метатаблица для mt.math. Затем

mt.math.floor = function(self) return math.floor(self.n) end 

будет работать должным образом. Например,

print(mt.math:floor()) 

печать 123.

EDIT 1: Так что теперь у меня есть лучшее понимание того, что вы пытаетесь сделать: как правило, вы могли бы сделать

p1:id() 
p1:getPos() 
p1:setPos() 
p1:getSpeed() 
p1:improveSpeed() 

Обратите внимание на двоеточие , это важно, так что каждый метод получает «я» как первый параметр, тем самым давая им экземпляр таблицы для работы (p1, в приведенном выше примере). Вместо этого вы хотите, чтобы групповые методы так

p1.info:id() 
p1.pos:get() 
p1.pos:set() 
p1.speed:improve() 
p1.speed:get() 

Эти методы получат себя, что указывает на p1.info, p1.pos и т.д. Но эти суб-таблицы не имеют никакого знания контейнера таблицы (p1). Таблицы info и pos находятся в классе Player: они делятся всеми экземплярами Player (p1, p2 и т. Д.). Вы должны сделать информацию и позы таблицы не разделяемую:

function Player:add(player) 
    local pN= setmetatable({n = player, info={}, pos={}}, {__index = Player}) 
    pN.info.id = function() return pN.n end 
    pN.pos.set = function(x) return setPosition(pN, x) end 
    return pN 
end 

Тогда вы получите

> p1=mt:add(player1) 
> p2=mt:add(player2) 
> print(player1) 
table: 0024D390 
> print(p1.info.id()) 
table: 0024D390 
> print(player2) 
table: 0024D250 
> print(p2.info.id()) 
table: 0024D250 

Все, что сказал, я не очень нравится идея того, чтобы использовать затворы, как это, возможно, есть gotchas, поскольку не все будет в Player.

+0

Не совсем так. Я хочу создать функции перед ее использованием. В вашем случае мне нужно сначала назначить 'mt: add()' в 'mt.math', а затем создать функцию' mt.math.floor'. Отредактировал мою проблему для более подробной информации. – Synchro

+0

@ user3225882 ОК Я расширил ответ на основе вашей новой информации. Я думаю, что понимаю, что вы сейчас пытаетесь сделать – Schollii

Смежные вопросы