Class Inheritance?

How does class inheritance work in Codea? I noticed that the class() function returns an object with an is_a() method, which implies that there’s some sort of OO going on. I tried a few obvious things but couldn’t make it work.

The class() function can take a base class as an argument, for example:

Dog = class(Animal)

I’ve pasted the Lua code for the class function below, for reference:

-- Class.lua
-- Compatible with Lua 5.1 (not 5.0).

function class(base)
    local c = {}    -- a new class instance
    if type(base) == 'table' then
        -- our new class is a shallow copy of the base class!
        for i,v in pairs(base) do
            c[i] = v
        end
        c._base = base
    end

    -- the class will be the metatable for all its objects,
    -- and they will look up their methods in it.
    c.__index = c

    -- expose a constructor which can be called by <classname>( <args> )
    local mt = {}
    mt.__call = function(class_tbl, ...)
        local obj = {}
        setmetatable(obj,c)
        if class_tbl.init then
            class_tbl.init(obj,...)
        else 
            -- make sure that any stuff from the base class is initialized!
            if base and base.init then
                base.init(obj, ...)
            end
        end
    
        return obj
    end

    c.is_a = function(self, klass)
        local m = getmetatable(self)
        while m do 
            if m == klass then return true end
            m = m._base
        end
        return false
    end

    setmetatable(c, mt)
    return c
end

Can someone post an example of initializing the base class and accessing globals and functions? I tried a few things but couldn’t get things working.

Apologies for the contrived example, hope it helps.

I think the key line is how to initialise the base class, it’s Base.init( self, … )

----------------
-- Class: Animal 
----------------

Animal = class()

function Animal:init( word )
    self.talk = word
end

function Animal:speak()
    print( self.talk )
end

----------------
-- Class: Dog
----------------

Dog = class(Animal)

function Dog:init()
    Animal.init( self, "Woof" )
end

----------------
-- Main
----------------

function setup()
    d = Dog()
    d:speak()

    c = Animal("Meow")
    c:speak()
end

Hmm, I tried that but it didn’t work - but now I see why. The classes are loaded in alphabetical order so you can only make subclasses with names that come later in the alphabet. For example, Dog can subclass Animal, but Aardvark cannot.

It looks like I can work around this by renaming the tab for my superclass to be early in the alphabet without actually renaming the class inside the tab. (You also have to close and reopen the project to get the tabs to reorder themselves.)

Ah that’s an issue we’ll have to look at fixing. Not sure of the best way to handle it, perhaps we can detect X = class(Y) statements and ensure Y is processed before X.

ah that probably explain issues I had with why sometimes initializing a variable in the global scope to the instance of a class doesn’t work.

Thanks for all the info. I couldn’t get my base class draw method to work. Once I renamed the tab of my base class alphabetically to come before my derived classes it worked perfectly.

Regarding alphabetically order loading of classes, it’s not a bug, it’s a feature. A part of Codea’s “magic”. :slight_smile:

I knew I’d see a comment from you, bee :stuck_out_tongue:

It is due to how Codea integrates your code, true. But I think there is a better option out there than require / module.

Hahahaha… :-))

Well… as like other kinds of magic, magic is fun, but only for people who doesn’t know the trick. For one who does, it’s kind of boring and sometimes annoying. :smiley: no pun intended

Is it possible to override a method and call that method in the super class? For example:

Blob = class(GameObject) function Blob:init() GameObject.init(self) end function Blob:update() -- How to make sure GameObject:update() is also called? end

GameObject.update(self)

Should do it - I’ll double check in a bit

Clarification, please - are the classes loading in alphabetical order, or the tabs? I am guessing it’s the tabs, and the load order within a single tab is in order of appearance? (I’d try it out, but it’s 5am here - I’m going back to bed!)

Bortels: within a file, statements are executed top to bottom. A “class definition” is just a statement that defines a variable to contain the result of calling the class() function. Method definitions are just statements that define functions.

GameObject.update(self)

That worked Simeon. Thanks!

Bortels: the tabs load in left-to-right order, which is usually alphabetical.

so, if I waned to take a class and extend the function to call the base class and then do additional processing, how would I do that in Codea?

For example, I want to create a Dog:speak() function that calls Animal:speak() and then does additional processing. When I try to do that by calling Animal:speak(), the variables in self are nil (makes some sense). However, I cannot figure out how to call the subclass and perform additional processing from the current class.

After hours of doing it wrong, I think the answer is: Animal.speak(self). Use a dot and not a colon!

Since this discussion has just resurfaced, let me point out that the parts about the order of loading of tabs are now antiquated as it is possible to reorder tabs.