Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Class Inheritance?

edited November 2011 in Questions Posts: 3

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.

Tagged:

Comments

  • SimeonSimeon Admin Mod
    edited November 2011 Posts: 5,386

    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.

  • SimeonSimeon Admin Mod
    edited November 2011 Posts: 5,386

    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.)

  • SimeonSimeon Admin Mod
    Posts: 5,386

    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.

  • edited November 2011 Posts: 447

    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.

  • beebee
    edited November 2011 Posts: 381

    Regarding alphabetically order loading of classes, it's not a bug, it's a feature. A part of Codea's "magic". :)

  • SimeonSimeon Admin Mod
    Posts: 5,386

    I knew I'd see a comment from you, bee :P

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

  • beebee
    Posts: 381

    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. :D no pun intended

  • edited November 2011 Posts: 2

    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

  • SimeonSimeon Admin Mod
    Posts: 5,386
    GameObject.update(self)
    

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

  • BortelsBortels Mod
    Posts: 1,557

    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!)

  • NatNat
    Posts: 143

    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.

  • Posts: 666

    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.

  • Posts: 666

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

  • edited August 2012 Posts: 2,161

    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.

  • Parts about the order of loading of tabs are now antiquated as it is possible to reorder tabs.

    Kind of a false logic, isn't it? Just stumbled on the error and I'm very happy I found this thread. Had to reorder my tabs.

  • Are there any plans to fix this?

  • Jmv38Jmv38 Mod
    edited December 2014 Posts: 3,297

    @mkarneim this discussion is obsolete (2 years old). When you copy a project by long press, you get the tabs in the correct order, so there is no problem.

This discussion has been closed.