# lua Class implementation not working, using __index

This topic is 2927 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Thought i would liven up the scripting thread a bit. I have an issue with my class implentation
Class = function( prototype )
local derived = {}
local derivedMT = {
--When indexing into a derived class, check the base class as well
__index = prototype,

--When invoking a class, return an instance
__call = function( proto, ... )
local instance = {}
local instanceMT = {
--When indexing into an instance, check the class hierarchy as well.
__index = derived,
--Calling instances is a no-no!
__call = function()
print( "WARNING! Attempt to invoke an instance of a class!" )
print( debug.traceback() )
return instance
end,
}
setmetatable( instance, instanceMT )

if ( instance.__constructor ) then
instance:__constructor( ... )
end

return instance
end,
}
setmetatable( derived, derivedMT )
return derived
end

for some reason when i try thing = class() function thing:Hello() print("hello") end SpecialThing = class(thing) SpecialThing:Hello(); it doesnt work! i should be able to call the base class function right? it sets the index property of the metatable? am i missing something? I can post my exact usage if this doesnt point out the problem. thanks...

##### Share on other sites
I haven't debug your class impl. but I've been using this one for awhile and it does everything I need.

function inheritsFrom( baseClass )	    local new_class = {}    local class_mt = { __index = new_class }    function new_class:create()        local newinst = {}        setmetatable( newinst, class_mt )        return newinst    end    if nil ~= baseClass then        setmetatable( new_class, { __index = baseClass } )    end    -- Implementation of additional OO properties starts here --    -- Return the class object of the instance    function new_class:class()        return new_class;    end		-- Return the super class object of the instance, optional base class of the given class (must be part of hiearchy)    function new_class:baseClass(class)		return new_class:_B(class);    end	    -- Return the super class object of the instance, optional base class of the given class (must be part of hiearchy)    function new_class:_B(class)		if (class==nil) or (new_class==class) then			return baseClass;		elseif(baseClass~=nil) then			return baseClass:_B(class);		end		return nil;    end		-- Return true if the caller is an instance of theClass    function new_class:_ISA( theClass )        local b_isa = false        local cur_class = new_class        while ( nil ~= cur_class ) and ( false == b_isa ) do            if cur_class == theClass then                b_isa = true            else                cur_class = cur_class:baseClass()            end        end        return b_isa    end    return new_classend

This is a slightly modified version of the one found on the Lua wiki. The difference is you pass the current class instance to get the super class (as the original code called it, i call it the base class), this is to support chained inheritance. The original code didn't work when the inheritance depth was greater than 1.

You would use it like so:

LevelBase = inheritsFrom( nil ); -- Create a table to hold the class methods function LevelBase:new() -- The constructor	local object = {mBaseStuff={1,2,3}};        setmetatable(object, {__index = LevelBase});	--setup metatable	return object endfunction LevelBase:callFunc(a,b)  print("base class function called "..a..","..b);endLevelDerived= inheritsFrom( LevelBase );  function LevelDerived:new() -- The constructor	local object = LevelBase:new();				object.mNewMember={2,3,4};	setmetatable(object, {__index = LevelDerived});	--setup metatable	return object end function LevelDerived:callFunc(a,b)  print("derived class function called "..a..","..b);endfunction LevelDerived:callFuncBase(a,b)  self:_B(LevelDerived).callFunc(self,"a,b);end

To call a base class function you will have to use this somewhat arcane convention.

self:_B(LevelDerived).callFunc(self,"hello","world");--or if you only have a single inheritance depth : self:_B().callFunc(self,"hello","world");

note the usage of the . calling convention and passing in self as the first param, that's needed, you can't use the : convention.

Hope this help! Enjoy!

-ddn

##### Share on other sites
Wow thanks so much.

I'll take a look at this in depth and see how i can use it.