On Sun, 2004-07-18 at 14:43 -0600, Ryan McDougall wrote: > The more I learn about what both type system and GObject do to create > instances, the more I come to the conclusion that the way it works is > way too complicated. I cannot think of a theoretical reason why fairly > simple constructor semantics wouldn't work, so I'm pretty sure there > must be a good practical reason ... however I'm not nearly experienced > enough to know what that might be. Can someone explain it to me? > > Specifically: > > In class object instantiation, why does it bother copying memory from > parent object to final when it will run the parent object's base_init on > the final object anyways? base_init takes no parameter, so its kind of > like a default constructor, no? Then anything that could be set with a > memory copy could be set with base_init. The only think that *couldn't* > be set is anything that was done to the class after base_init, which > should hopefully only be class_init. So why should we have a class_init > at all? Because class_init takes a parameter? Then why doesn't base_init > take a parameter? base_init() is called exactly once -- it's useful for initializing classwide variables (e.g. a hash table of all the existing objects in that class) that should only be initialized once. class_init() is called once-per-class (and subclass) to add the required properties, signals, and method/signal overrides to the desired class structure, which will be different for every subclass. > Why does GObject implement its own constructor on top of the > instance_init constructors? Worse of all it makes you manually chain up > the parent constructors. If GObjects have their own constructors, then > isn't instance_init basically redundant and useless? I know the GObject > constructor is there to support properties, but couldn't we give > instance_init a parameter and just be done with it? Here's how the basic object creation sequence works: base_init() [only once] allocate the class structure class_init() [if it hasn't already been called for this class in this hierarchy] constructor() [per-instance] first, chain-to-parent, which: --> allocates the instance structure. --> calls instance_init() --> calls set_property() for G_PARAM_CONSTRUCT properties user-defined body of constructor() set_property() for non-CONSTRUCT properties. When the user does not override the constructor() method, then the allocation method *appears* to be: base_init() class_init() instance_init() set_property() I personally use instance_init() to set any instance variables (like - >priv), create any data structures (i.e. property defaults and anything I'd free in finalize()), etc. I use constructor() to fill in any dependent objects, child widgets, etc. (i.e. things I'd free in dispose ()). Overriding constructor() is typically not necessary (I could just as easily create the child widgets in instance_init, for example), so it may very well be redundant, but AFAICT the idea is to allow programmers to do things between set_property() for CONSTRUCT properties and set_property() for regular properties. Often that doesn't need to be done, but dispose() will typically not need to be overridden either (only when one object holds [circular] references to other objects). The destruction sequence is: dispose() [release any references to other objects] finalize() [free any additional data] class_finalize() [if no remaining instances, called once-per-class for dynamic types] base_finalize() [called only once for dynamic types] I can't really comment on whether or not it's too complicated for users, but everything in there has a reason why it exists, and changing it now would require breaking every object in existance, which would really suck :-). -- Peace, Jim Cape http://esco.mine.nu http://ignore-your.tv "If even one reporter had stood up during a pre-Iraq Bush press conference last year and shouted, `Bullshit!' it might have made a difference." -- Matt Taibbi, New York Press
Attachment:
signature.asc
Description: This is a digitally signed message part