2011-07-07 20 views
1

這是我想使用Lua C API在C++中執行的操作。如何設置metatable從另一個metatable繼承,同時將userdata更改爲另一個類型?

我想弄清楚一個很好的方法,使userdata派生自一個基本的userdata對象。

我希望能夠做到這一點:

local item = me:GetCurrentItem() 
print(item:GetPos()) 

代替:

local item = me:GetCurrentItem() 
print(item:GetBaseObject():GetPos()) 

在這些例子中,我說:GetCurrentItem()返回用戶數據的一些功能,但它缺乏基礎item:GetBaseObject()返回的函數。

我在Crysis Wars SDK中綁定Lua用於學習目的。 SDK爲基礎實體提供了一個接口,它是一個結構體。 IItem結構(我:GetCurrentItem())是相同的。 由於這些是結構體,我不能將它們轉換爲基本結構或調用其基本函數。我必須使用IEntity * GetEntity()函數。

我試着在__index中查看自我指針,但它會導致局部變量「item」變成「實體」,這很明顯,但我希望它在調用GetPos函數後恢復回來,這似乎不合邏輯。

有沒有人有這個問題的很好的解決方案?

回答

2

明顯的解決方案是定義一個項目:重定向的GetPos()函數。

function Item:GetPos() 
    return self:GetBaseObject():GetPos() 
end 

其中Item是項目的metatable。

這與在metatable上進行更改一樣高效,而且問題較少。

編輯:我也可以幫你一點重複。

可以實現以下兩個功能:

function delegate(klass, methodName, memberName) 
    klass[methodName] = function(self, ...) 
    local member = self[memberName] 
    if type(member) == 'function' then member = self[memberName](self) end 
    return member[methodName](member, ...) 
    end 
end 

,然後用它是這樣的:

delegate(Item, 'GetPos', 'GetBaseObject') 

這一行做對子級與上述相同的Item:GetPos 3線定義。

如果您需要重複這個有很多,你可以進一步與該其他職能優化它:

function delegateMany(klass, methodNames, memberName) 
    for _,methodName in ipairs(methodNames) do 
    delegateMethod(klass, methodName, memberName) 
    end 
end 

應該使你可以這樣做:

deletageMany(Item, {'GetPost', 'SetPos', 'GetColor', 'SetColor'}, 'GetBaseObject') 

我沒有測試任何這些功能,所以要小心錯誤。他們應該同時使用「已獲得的屬性」(self:GetSomething()以及簡單訪問self.something)。該代碼假設您總是使用'​​:'來調用委託方法,因此在需要時添加self

+0

我想這樣做,如果沒有好方法。由於基礎實體具有許多我將要使用的功能,因此在所有類中再次添加相同的功能將是一個非常重複的任務。 – CapsAdmin

+0

也許我只需要認識到這是正確的方法。 – CapsAdmin

+0

@CapsAdmin重複代碼從來就不是好事。我添加了一些代碼,可以讓你以更清晰的方式做你想做的事。如果您有任何問題,請告訴我。 – kikito

相關問題