Sign in to follow this  
AverageJoeSSU

lua Class implementation not working, using __index

Recommended Posts

AverageJoeSSU    564
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 this post


Link to post
Share on other sites
ddn3    1610
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_class
end






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
end

function LevelBase:callFunc(a,b)
print("base class function called "..a..","..b);
end

LevelDerived= 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);
end

function 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 this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this