Page 1 of 1

Method doesn't see self variable when called by other method (hump.class)

Posted: Sat Mar 09, 2024 3:34 pm
by Sense
Newbie question. I created a class with hump.class and try to access one of its variables in a method called by another method.
The sub-method doesn't see the self. variable (nil). What do I miss?

Output of the program below:
Var in main 5
Var in sub nil

Code: Select all

Class = require 'lib/class'
MyObject = Class {}

function MyObject:init(i)
	self.myVar = i
end

function MyObject:mainMethod()
	print('Var in main', self.myVar)
	MyObject:subMethod()
end

function MyObject:subMethod()
	print('Var in sub', self.myVar)
end

i = MyObject(5)
i:mainMethod()

Re: Method doesn't see self variable when called by other method (hump.class)

Posted: Sat Mar 09, 2024 5:22 pm
by Bobble68
Your issue is this:

Code: Select all

function MyObject:mainMethod()
	print('Var in main', self.myVar)
	MyObject:subMethod()
end
What you want is

Code: Select all

function MyObject:mainMethod()
	print('Var in main', self.myVar)
	self:subMethod()
end
Assuming I understand how this class library works, what you're doing is you're using the class itself (which of course is never initialised), rather than that specific object.

Re: Method doesn't see self variable when called by other method (hump.class)

Posted: Sat Mar 09, 2024 5:48 pm
by Sense
Many thanks. it works!
I came across this Class library on the Harvard CS50 Gaming course. Is there another one you’d recommend/are using?

Re: Method doesn't see self variable when called by other method (hump.class)

Posted: Sat Mar 09, 2024 6:04 pm
by MrFariator
Classic is perfectly fine to use. If you want a list of other libraries, you can find a list here (under "OO", object orientation). Each library has their pros and cons, so essentially pick the one you like.

Re: Method doesn't see self variable when called by other method (hump.class)

Posted: Sat Mar 09, 2024 8:01 pm
by Bobble68
Classic is the one I use, though it's mainly because it was the one used in the sheepolution tutorials, so I can't really say much about the quality of this or other ones.

Re: Method doesn't see self variable when called by other method (hump.class)

Posted: Sat Mar 09, 2024 8:17 pm
by RNavega
Sense wrote: Sat Mar 09, 2024 5:48 pm Is there another one you’d recommend/are using?
I think that the mechanism being used to simulate this sort of templating / class inheritance (the __index metamethod from a metatable) is simple enough that you can reimplement it yourself, without the need for an entire library (unless you need the other parts from it of course).

For instance, from my personal utilities module, the class-like helper is this:

Code: Select all

local BaseObject = {}

function BaseObject._new(base, ...)
    local t = setmetatable({}, base)
    -- Run the init function if present, using the "instance" as self.
    if base.init then
        base.init(t, ...)
    end
    t.__index = t
    t.__call = BaseObject._new
    return t
end

function BaseObject.final(base, ...)
    local t = setmetatable({}, base)
    if base.init then
        base.init(t, ...)
    end
    t.__index = t
    t.__call = BaseObject._finalNew
    return t
end

function BaseObject._finalNew(base, ...)
    local t = setmetatable({}, base)
    if base.init then
        base.init(t, ...)
    end
    return t
end
BaseObject.__index = BaseObject
BaseObject.__call = BaseObject._new
setmetatable(BaseObject, {__call=BaseObject._new})
Used like this:

Code: Select all

local A = BaseObject()

function A:init(args)
    print('A:init()', 'args:', args)
end

print('Creating instance of A...')
local B = A(123)

function B:init(args)
    print('B:init()', 'args:', args)
end

print('Creating (final) instance of B...')
-- As I understand it, a final inheritance is one where you can't subclass
-- any more, just make instances from it.
local instance = B:final(456)
This mechanism is explained in these links:
- https://www.lua.org/pil/13.4.1.html
- https://www.lua.org/pil/16.html#ObjectSec

PS as it says in the PIL, another way to have tables following the same "interface" is to use a function where you organize all the common fields that they should have:

Code: Select all

local function method1(self, arg1, arg2)
    ...
end


local function method2(self, arg1, arg2)
    ...
end


local function createTemplate(instance)
    instance = instance or {}
    instance.myMethod1 = method1
    instance.myMethod2 = method2
    instance.valueA = 123
    instance.valueB = 456
    return instance
end


local instanceA = createTemplate()

local instanceB = createTemplate()
This should be slightly faster than using that metatable mechanism, since it doesn't need the double-lookup (looking up the key on the "instance" table, not finding it, then looking it up on the __index table). In fact I'm thinking of going with this on some speed-critical code.

Re: Method doesn't see self variable when called by other method (hump.class)

Posted: Sat Mar 09, 2024 9:41 pm
by Sense
Thanks all. Great community!

Re: Method doesn't see self variable when called by other method (hump.class)

Posted: Sat Mar 09, 2024 11:46 pm
by pgimeno
RNavega wrote: Sat Mar 09, 2024 8:17 pm This should be slightly faster than using that metatable mechanism, since it doesn't need the double-lookup (looking up the key on the "instance" table, not finding it, then looking it up on the __index table). In fact I'm thinking of going with this on some speed-critical code.
Apparently it can indeed be slow, especially if there are multiple inheritance levels. Of course the JIT compiler will flatten out these lookups if they get compiled; the problem comes when they're not.

See viewtopic.php?p=231457#p231457 and the next post.

Re: Method doesn't see self variable when called by other method (hump.class)

Posted: Sun Mar 10, 2024 3:42 am
by RNavega
pgimeno wrote: Sat Mar 09, 2024 11:46 pm See viewtopic.php?p=231457#p231457 and the next post.
Thanks for that reference, very interesting.

AFAIK it seems that the JIT compiles "hot paths" / frequently executed code when it hits some specific loop cycle count, the default settings for which can be seen at the bottom of this page: https://luajit.org/running.html
It's tempting to change it to be extremely sensitive. Like forcing it to compile your entire app heh

Edit: noticed a bug in that BaseObject code I posted, I updated it.