4

Luaでゲームフレームワークを使用しています。ここで、ボタンを作成する場合は、関数と2つのスプライト(ボタンの上下)を保持するボタンのテーブルを作成します。

スプライトには、setLocation(self, x, y)やなどの基本的な機能がたくさんありgetDimensions(self)ます。

私はこのような多くの関数を作成したくありません:

function button.setLocation(self, x, y)
   self.buttonUpSprite(self, x, y)
end

ただし、ボタンに対して行われたほとんどの呼び出しを直接buttonUpスプライトに「自動的に」委任したいと思います。

ボタンテーブルのメタテーブル__indexをスプライトを指すように設定するだけで、呼び出しはスプライトの関数を転送しますが、self参照はボタンを指し、操作したいスプライトではありません。

この委任を行うためのクリーンな方法はありますか?

4

1 に答える 1

3

ネストされたメタテーブルを使用して、オンデマンドでリダイレクト機能を自動的に構築できます。

----------------------------------
-- sprite.lua
----------------------------------
local Sprite = {}

local mt = {__index = Sprite}

function Sprite.new(filename)
   local sprite_object = {
      img = load_image_from_file(filename),
      x = 0,
      y = 0
   }
   return setmetatable(sprite_object, mt)
end

function Sprite:setLocation(x, y)
   self.x = x
   self.y = y
end

function Sprite:getDimensions()
   return self.img.getWidth(), self.img.getHeight()
end

return Sprite

----------------------------------
-- button.lua
----------------------------------
local Sprite = require'sprite'
local Button = {}

local function build_redirector(table, func_name)
   local sprite_func = Sprite[func_name]
   if type(sprite_func) == 'function' then
      Button[func_name] = function(button_object, ...)
         return sprite_func(button_object.up_sprite, ...)
      end
      return Button[func_name]
   end
end

local mt = {__index = Button}            -- main metatable
local mt2 = {__index = build_redirector} -- nested metatable

function Button.new(upSprite)
   return setmetatable({up_sprite = upSprite}, mt)
end

return setmetatable(Button, mt2)

----------------------------------
-- example.lua
----------------------------------
local Sprite = require'sprite'
local Button = require'button'

local myUpSprite = Sprite.new('button01up.bmp')
local myButton = Button.new(myUpSprite)

myButton:setLocation(100, 150)
-- Sprite.setLocation() will be invoked with sprite object as self

print(myButton:getDimensions())
-- Sprite.getDimensions() will be invoked with sprite object as self
于 2013-02-17T11:00:16.123 に答える