I am able to inherit a value "hunger" from a parent class (Animal) and see its value in the child class (Dog), but I cannot seem to change it in the child class through any function not named init. I made a test project (below) and it somehow works fine, but I can't seem to replicate it in my actual project.
--animal.lua:
Animal = Core.class(Sprite)
function Animal:init()
self.hunger = 50
print("Animal:"..self.hunger)
end
function Animal:setHunger(hunger)
self.hunger = hunger
print("setHunger(): "..self.hunger)
end
function Animal:getHunger()
print("getHunger(): "..self.hunger)
return self.hunger
end
--dog.lua
Dog = Core.class(Animal)
function Dog:init()
print("Dog:"..self.hunger)
end
function Dog:callMe()
print("callMe(): "..self:getHunger())
end
--main.lua:
local d = Dog.new()
d:setHunger(20)
d:callMe()
------------------
-- Output:
------------------
Animal:50
Dog:50
setHunger(): 20
getHunger(): 20
callMe(): 20 |
The output is as expected. Created a Dog object first calls Animal's init() method which prints the first line, then Dog's init() method prints the second line.
Calling "d:setHunger(20)" calls the inherited method from Animal, printing the third line.
Calling "d:callMe()" first goes into Animal's getHunger() method resulting in the fourth line, and then back up in hierarchy to finally print the fifth line. The values are all correct.
Now, in my actual project, I am trying to do the same thing, but the Dog class calling getHunger() is resulting in the "old" value.
------------
breed.lua
------------
Breed = Core.class(Sprite)
function Breed:init()
self.hunger = 20
local timer = Timer.new(5000, 0)
timer:addEventListener(Event.TIMER, self.statusUpdate, self)
timer:start()
end
function Breed:needUpdate(event)
if self.hunger <= 95 then
self:setHunger(self.hunger + 5)
print("Hunger set to "..self:getHunger())
end
end
function Breed:statusUpdate(event)
self.needUpdate(self)
end
function Breed:setHunger(hunger)
self.hunger = hunger
end
function Breed:getHunger()
return self.hunger
end
------------
dog.lua
------------
Dog = Core.class(Breed)
function Dog:init()
local timer = Timer.new(5000,0)
timer:addEventListener(Event.TIMER, self.updateMeters, self)
timer:start()
end
function Dog:updateMeters(event)
local h = self:getHunger()
print("updateMeters(): "..h)
end
------------------
-- Output: (Multiple outputs as timer goes on)
------------------
Hunger set to 25
updateMeters(): 20
Hunger set to 30
updateMeters(): 20
Hunger set to 35
updateMeters(): 20
Hunger set to 40
updateMeters(): 20 |
I tried to cut out most of the code that was irrelevant.
So, every 5000 ms two timers are going off: one in the Breed class (Breed:NeedUpdate()) which increases self.hunger by 5, and one in the Dog class (Dog:updateMeters()) which just prints self.hunger through the inherited getHunger() method. I am not understanding why the second printed line from updateMeters() is always printing 20, when the value is clearly being changed in the needUpdate() method.
I am sorry for the long-winded question, I just wanted to be thorough! Thanks for any help!
-J
Comments
Testing this out on a simpler example, the value of self is different in the two init calls ...
So ... addEventListener in Breed.init adds an event listener that references a different table than the addEventListener in Dog.init ... and since they're different, they each have their own version of "hunger".
I don't know whether @atilim will consider this a bug, but it's not the behavior I'd expect.
--ND
1. Name your "init" functions something else, e.g., "construct"
2. Add an explicit call to the base class construct method as the first line in your construct functions
3. After you create a class, call its construct method.
Example:
If memory serves "self" is actually a reference to the table that contains the function being executed and is passed in as a first "hidden" parameter when calling a table function with : as opposed to .
ie.
table.function(self,param) is the same as table:function(param)
in both cases you can reference "self" from within the function and get the same value.
#MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
Thanks!
-J
@techdojo IIRC in C++, using the "this" reference in A to work with parameters should still change those parameters in B (if the object created is a . This is what seems to be the problem, as changing "hunger" in the Breed class is not changing "hunger" in the Dog class because the Dog class's "hunger" contains a different instance of "hunger", a deep copy from the Breed class rather than the shallow one I expect/need.