Opened 12 years ago

Closed 12 years ago

Last modified 12 years ago

#4243 closed defect (fixed)

preambles invoked multiple times and after constructors

Reported by: guest Owned by: sjmiles
Priority: high Milestone: 1.0
Component: Core Version: 0.9
Keywords: Cc:
Blocked By: Blocking:

Description

Given a Parent, two mixins (Mixin1 and Mixin2) and a Child declared like this:

dojo.declare("Parent", null, {...});
dojo.declare("Mixin1", null, {...});
dojo.declare("Mixin2", null, {...});
dojo.declare("Child", [Parent,Mixin1,Mixin2], {...});

The preamble and constructor functions are called in the following order when creating an instance of Child:

Child.preamble
Mixin2.preamble
Mixin1.preamble
Parent.preamble
Parent.constructor
Mixin1.preamble
Mixin1.constructor
Mixin2.preamble
Mixin2.constructor
Child.constructor

There doesn't appear to be a way to attach a file when creating a ticket. After it's created, I'll see if I can attach a test file. Otherwise I guess I'll just inline the code...

Attachments (1)

declare.html (1.8 KB) - added by guest 12 years ago.
Simple test for preamble and constructor order

Download all attachments as: .zip

Change History (7)

Changed 12 years ago by guest

Attachment: declare.html added

Simple test for preamble and constructor order

comment:1 Changed 12 years ago by bill

Milestone: 1.0
Owner: changed from anonymous to sjmiles

comment:2 Changed 12 years ago by sjmiles

Resolution: fixed
Status: newclosed

(In [10323]) Prevent duplicating 'preamble' in intermediate delegates, fixes #4243.

comment:3 Changed 12 years ago by sjmiles

Resolution: fixed
Status: closedreopened

[10323] is a start, but I'm not actually ready to close this.

comment:4 Changed 12 years ago by sjmiles

Resolution: fixed
Status: reopenedclosed

So the new flow is as follows:

Child.preamble
Parent.preamble
Parent.constructor
Mixin1.preamble
Mixin1.constructor
Mixin2.preamble
Mixin2.constructor
Child.constructor

This is actually how it is intended to work, although it may not be intuitive. Note that mixins themselves can have complex hierarchies, and preamble is intended primarily to allow a class to manipulate the arguments that will be passed to it's superclass. In other words, there is an important branching ability in preamble.

I expect that some users expect all preambles to be called in inverse order to constructor, which unfortunately is a different concept.

In particular, you might expect this when descending from a class like dijit._Widget, which initiates a create process in it's constructor. Because base class constructors operate first, there is no room for subclasses to initialize values before create. preamble was used to solve this problem, but when used with mixins it's not exactly the same thing, as described above.

The simplest solution is that subclasses override create in order to do initialization. Understandably, this feels odd since it really makes constructor useless in subclasses.

Alternatively, we can provide another function, perhaps postscript, that is invoked after all construction tasks, which is really more to the point.

comment:5 Changed 12 years ago by sjmiles

I meant to say that a function like postscript could be supported directly by declare.

comment:6 Changed 12 years ago by sjmiles

(In [10329]) Call "postscript" method after construction, refs #4243.

Note: See TracTickets for help on using tickets.