kikito / middleclass

Object-orientation for Lua
https://github.com/kikito/middleclass
MIT License
1.77k stars 190 forks source link

How to use __call #31

Closed CriztianiX closed 9 years ago

CriztianiX commented 9 years ago
local class = require "lua-resque.deps.middleclass"
local redis = require 'redis'

local Resque_Redis = class('Resque_Redis')
function Resque_Redis:initialize(sredisServer, sredisDatabase)
  local client = redis.connect('127.0.0.1', 6379)
  self.client = client
  return client
end
function Resque_Redis.__call(m)
  self.client[m]("q")
end

return Resque_Redis

Trying to use it:

local r = Resque_Redis:new()
r:sadd('queues', queue)
attempt to call method 'sadd' (a nil value)
qaisjp commented 9 years ago

Not quite sure what you're doing there, but off the top of my head (and writing this on mobile), __call works like this in pure Lua:


local tab=setmetatable({},
{
__call=function(t, ...)
  print("Args:", ...)
end
})

tab.regulartable = "yeah"

tab("Hello", "world")
-- > Args:  Hello  World

tab(1, 2, 3)
-- > Args:  1  2  3

print(tab.regulartable)
-- > yeah
kikito commented 9 years ago

@CriztianiX I think you are mistaking the __call metamethod with the __index metamethod.

As @qaisjp says, __call basically allows "using an instance of a class as a function". So if the class S has the __call method defined, and s is an instance of S, you can do s('foo').

__index is the metamethod to call when "you call something which does not exist in a table". Unfortunately I need to use __index to implement the basic functionality of middleclass, so I can't support it.

In your particular case, you can get around this issue by using a bit of metaprogramming, defining all the methods you need. It should look similar to this:

local class = require "lua-resque.deps.middleclass"
local redis = require 'redis'

local Resque_Redis = class('Resque_Redis')
function Resque_Redis:initialize(sredisServer, sredisDatabase)
  local client = redis.connect('127.0.0.1', 6379)
  self.client = client
  return client
end

local redis_methods = { 'sadd', 'srem' } -- add more methods here
for i=1,#redis_methods do
  local method = redis_methods[i]
  Resque_Redis[method] = function(self, ...)
    return self.client[method](...)
  end
end

Add the methods you need to the table redis_methods and they will be available for each instance.