The problem is that you are mixing functions and methods. (I don’t know your level of programming so I don’t know how to pitch this explanation - my apologies if I get it wrong.)
When you define a class, you define - as you do - a load of methods for use with that class. These become available when you declare an object of that class, but they have to[1] be called on a an actual object, otherwise Things Go Wrong. So when you call a method, you have to be sure that the method knows which object it should be called on.
When you pass the callbacks to the subclasses (B and C) then all you are actually passing is the method. You aren’t passing the object on which they should be called, so when the method gets called it is called with a nil
object. But the callback, which is A:aDo
, needs to know its object because it uses it: self.c:callB()
.
The basic problem is that you can’t pass a method and its object in a single pass. You can pass an object, together with all of its attendant methods but this doesn’t seem to be what you want to do. So you need to pass the method and its object together, for example you could have:
A = class()
function A:init()
self.b = B(self,self.aDo)
self.c = C(self,self.b.bDo)
end
Then in the B and C class, something like:
function B:init(caller,callback)
self.caller = caller
self.callback = callback
end
function B:callA()
self.callback(self.caller)
end
Then the B object knows not only what method to call on its “parent”, but also who its parent actually is.
Incidentally, you can’t pass an object-and-method by passing the colon form of the method, so self.b = B(self:aDo)
doesn’t work. It seems that the internal magic that converts instance:doSomething()
to class.doSomething(instance)
happens at the moment that lua encounters the colon and so lua tries to process the function there and then, which doesn’t work well.
[1] Well, not strictly. But if you don’t do this, you should definitely know what you are doing so it’s one of those rules that can only be broken if you know that you’re breaking it.