2014-01-23 24 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.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 

當我把球員:get()方法在我的方法,它的返回最後一個對象聲明。

+0

我不確定我是否完全理解這個問題,但在這些內部函數中'self'將會是'mt.math' /'mt.effect'表,而不是頂級'mt'表這並不明確。 –

+0

有什麼方法可以打電話給mt嗎? – Synchro

+0

如果你給你的mt表一個'__call' metamethod它可以被調用。我不確定這與你的問題有什麼關係。 –

回答

0

基於你的狀態是什麼,如果你做

mt.math = mt:add(123) 

你不需要mt:get()因爲MT是mt.math元表。然後

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

將按預期工作。例如,

print(mt.math:floor()) 

打印123

編輯1:所以現在我有一個更好的瞭解你正在嘗試做的事:通常你會做

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

注意冒號,這是很重要的,這樣每個方法都會得到一個「self」作爲第一個參數,從而爲他們提供表實例來操作(在上面的例子中爲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等)。你必須使信息和POS表非共享:

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 

所有這一切說,我真的不喜歡不必使用倒閉這樣的想法,也許有一些問題,因爲不是所有的東西都會在播放器中播放。

+0

不完全是。我想在使用它之前創建功能。在你的情況下,我需要首先將'mt:add()'賦值給'mt.math',然後創建函數'mt.math.floor'。編輯我的問題了解更多詳情。 – Synchro

+0

@ user3225882好的,我根據你的新信息擴展了答案我想我明白你現在要做的是什麼 – Schollii