Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Accessing children from parent class — Gideros Forum

Accessing children from parent class

ar2rsawseenar2rsawseen Maintainer
edited June 2012 in General questions
Is this a bug, or this wasn't meant to be used this way? Basically I create my own class derived from Sprite and inside constructor I add eventlistener to mouse down, to iterate through all children of this custom sprite.
Then I extend this custom class, and add method for adding children. And when I start it and click it, it simply dies without any error message

Here's an example code:
MyClass = Core.class(Sprite)
 
function MyClass:init()
	self:addEventListener(Event.MOUSE_DOWN, self.handler, self)
end
 
function MyClass:handler()
	local children = self:getNumChildren()
	for i = 1, children do
		local sprite = self:getChildAt(i)
		print(sprite)
	end
end
 
MyExtendedClass = Core.class(MyClass)
 
function MyExtendedClass:add(elem)
	self:addChild(elem)
end
 
local container = MyExtendedClass.new()
stage:addChild(container)
container:add(Bitmap.new(Texture.new("crate.png")))
container:add(Bitmap.new(Texture.new("crate.png")))
container:add(Bitmap.new(Texture.new("crate.png")))
container:add(Bitmap.new(Texture.new("crate.png")))
If I do the same for each extended class it works great, problem is only if I iterate in parent class. It retrieves getNumChildren() correclty but dies on local sprite = self:getChildAt(i)

If it's not meant to be used this way, is there any other way I can reuse my code, so I won't have to write the same functions on all extended classes?

Comments

  • @ar2rsawseen i tried your code, and it really crashed the simulator or the iphone gideros player. Is it a bug?
    have fun with our games~
    http://www.nightspade.com
  • When I click, the handler fires twice as well. I wonder if this might be related to how the parent class is stored.
  • It still crashes when I do this, but if I add a blank declaration for MyExtendedClass:init the event handler only fires once.
  • ar2rsawseenar2rsawseen Maintainer
    edited June 2012
    hmm, that's interesting, so there is a purpose for constructors. :)

    But let's wait and see what @atilim has to say. I'm not saying it is a bug, maybe it was not suppose to work that way, I just want to know if it so, I would simply stop wasting my time and look for other solution :)
    Like static methods and retrieving event target, or something similar
  • atilimatilim Maintainer
    edited June 2012
    ohhh... lovely bug :)

    This is because of there are two different selfs when you inherit multiple times. @ar2rsawseen, most probably you remember this thread: http://www.giderosmobile.com/forum/discussion/834/possible-bug-self-in-base-class-init-function-is-not-equal-to-self-in-the-derived-class-init

    The exact solution is dropping the deep copying and always make sure that there is always one self. And in your specific example, the solution is moving the line
    self:addEventListener(Event.MOUSE_DOWN, self.handler, self)
    to MyExtendedClass's constructor. So that you register the event with the correct self.

    @ndoss said that two different selfs can cause subtle & difficult to find problems and this is a great example of it.

    Similar to your example, this code also crashes exactly with the same reason:
    local sprite = Sprite.new()
     
    sprite:addChild(Sprite.new())
    sprite:addChild(Sprite.new())
    sprite:addChild(Sprite.new())
    sprite:addChild(Sprite.new())
     
    sprite.__children = nil  -- mess with internal data
     
    sprite:getChildAt(1)
    This is not a bug because I always assume that users don't mess with internal data therefore I don't check consistency to be more efficient.

    thank you :)
  • ar2rsawseenar2rsawseen Maintainer
    I knew I've read somewhere about it. Just could not remember.
    Ok thanks, moving addEventListener helps and everything works as expected ;)
  • Wait.... we can inherit from custom classes that we create? Or extend them? I thought I read that didn't work. I guess I'll have to try something like that.
  • @atilim what is the future for this : "there are two different selfs when you inherit multiple times"?
    Let me change deep copy to shallow copy and test extensively.
    (And honestly I don't remember why I preferred deep copy instead of shallow )
    Any updates, or is the solution that you suggested the definitive one to remember, use now and in the future?
    twitter@TheWindApps Artful applications : The Wind Forest. #art #japan #apps
  • Wait.... we can inherit from custom classes that we create? Or extend them? I thought I read that didn't work. I guess I'll have to try something like that.
    Yes, you can inherit from your own classes. Wasn't always that way...you probably read older documentation
  • @ndoss Oh that's awesome, I'm glad that was added!
  • atilimatilim Maintainer
    edited July 2012
    yay! I'm back..

    here is the old Core.class function:
    Core.class = function(b)
        local c = {}
        c.__index = c
        setmetatable(c, b)
     
        if b == nil then
            c.new = function(...)
                local s1 = {}
     
                setmetatable(s1, c)
     
                if s1.init ~= nil and type(s1.init) == "function" then
                    s1:init(...)
                end
     
                return s1        
            end
        else
            c.new = function(...)
                local b = getmetatable(c)
     
                local s0 = b.new(...)
                local s1 = {}
     
                for k,v in pairs(s0) do
                    s1[k] = v
                end
     
                setmetatable(s1, c)
     
                if s1.init ~= nil and type(s1.init) == "function" then
                    s1:init(...)
                end
     
                return s1
            end
        end
     
        return c
    end

    and here is the new one:
    Core.class = function (b)
        local c = {}
        c.__index = c
        setmetatable(c, b)
     
        if b == nil then
            c.new = function(...)
                local s1 = {}
     
                setmetatable(s1, c)
     
                local init = rawget(c, "init")
                if type(init) == "function" then
                    init(s1, ...)
                end
     
                return s1		
            end
        else
            c.new = function(...)
                local b = getmetatable(c)
     
                local s1 = b.new(...)
     
                setmetatable(s1, c)
     
                local init = rawget(c, "init")
                if type(init) == "function" then
                    init(s1, ...)
                end
     
                return s1
            end
        end
     
        return c
    end
    @Mells if you want, you can create an init.lua file and copy the new Core.class function into it to override the old one.
  • @Atilim - will this fix be in the next update?
    WhiteTree Games - Home, home on the web, where the bits and bytes they do play!
    #MakeABetterGame! "Never give up, Never NEVER give up!" - Winston Churchill
  • gorkemgorkem Maintainer
    @techdojo fixed :) due next release ;)

    Likes: techdojo

    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.