CrazyCactuaR
CrazyCactuaR

Reputation: 67

Unable to figure out lua table inheritence

Hope someone can make sense of what I'm attempting to figure out, Just don't seem to understand Lua enough to achieve this.

--[[
    tbl.a.test("moo") returns "Table A moo appears"
    tbl.b.test("moo") returns "moo appears"
]]
tbl = {
    a = { ID = "Table A" },
    b = {
        test = function(...) print(... .. " appears") end,
    }, 
}
tbl.a__index = function(self, ...) tbl.b[self](tbl.a.ID .. ...) end

What I'm attempting to do is I could create several tables a, c, d, e and not have to copy test to each one. When tbl.a.test, tbl.c.test, tbl.d.test is used, It'll retrieve the tbl.a.ID var, then call tbl.b.test(ID, "moo")

So far all I'm finding out is it's not able to find .test on anything other than tbl.b

** EDIT ** Thank's to support so far the code is now;

tbl = {
    a = { ID = "Table A " },
    b = { test = function(...) local id, rest = ... print(id .. ": " .. rest)     end },
}
setmetatable(tbl.a, {__index=function(self, k, ...) local rest = ... return     tbl.b[k](tbl.a.ID, rest) end})

However, the ... is not being progressed for some odd reason :|

Upvotes: 2

Views: 86

Answers (2)

tonypdmtr
tonypdmtr

Reputation: 3225

--------------------------------------------------------------------------------
-- [Sub]Class creation
--------------------------------------------------------------------------------

function newclass(new_obj,old_obj)
  old_obj = old_obj or {}               --use passed-in object (if any)
  new_obj = new_obj or {}
  assert(type(new_obj) == 'table','New Object/Class is not a table')
  assert(type(old_obj) == 'table','Old Object/Class is not a table')
  old_obj.__index = old_obj             --store __index in parent object (optimization)
  return setmetatable(new_obj,old_obj)  --create 'new_obj' inheriting 'old_obj'
end

--------------------------------------------------------------------------------

prototype = {
  test = function(self,s) print('Table ' .. self.id .. ' ' .. s .. ' appears') end
}

tbl = {}

tbl.a = newclass({id = 'A'},prototype)
tbl.b = newclass({id = 'B'},prototype)

tbl.a:test('moo')
tbl.b:test('moo')

The distinction between class and object in Lua is only theoretical. In practice they are implemented exactly the same way.

Anytime you need to do inheritance, you can use my general-purpose newclass() function to either create a new class/object, or inherit from an existing one.

Any common code & data you would like to have passed on should go into the 'prototype' table (whatever you'd like to call it for each case).

Also, you seem to forget to use the method calling syntax (that uses a colon instead of a dot) when calling methods. Without it, the self parameter is not automatically recognized.

Upvotes: 1

Colonel Thirty Two
Colonel Thirty Two

Reputation: 26549

  • You're missing a period between tbl.a and __index.
  • __index needs to be on a's metatable, not the table itself.
  • You don't return anything from your __index function
  • self in the __index function is the table being indexed, not the key (which is the second argument)

This should work:

setmetatable(tbl.a, {__index=function(self, k) return tbl.b[k](tbl.a.ID) end})

Upvotes: 3

Related Questions