[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Import order question

 Terry Reedy <tjreedy at udel.edu> Wrote in message:
> On 2/17/2014 8:01 AM, Nagy L??szl?? Zsolt wrote:
>> I have a class hierarchy like this:
>> Widget <- VisualWidget <- BsWidget
>> and then BsWidget has many descendants: Desktop, Row, Column, Navbar etc.
>> Widgets can have children. They are stored in a tree. In order to manage
>> the order of widgets, I need methods to append children. (And later:
>> insert or prepend because they also have an order). So I would like to
>> have methods like this:
>> BsWidget.AppendNavbar(....)
>> BsWidget.AppendRow(...)
> I would write one prepend/insert/append method that 
> prepends/inserts/appends the widget passed.
>> Here is the problem: these methods should create instances of Row,
>> Column and Navbar.
> I disagree, without strong justification. Create the instances by 
> directly calling the classes and do with them as you want.

I agree with Terry,  and will try to justify it. Whenever you have
 a large group of modules recursively importing each other,  you
 need to look hard at the reason. (And saying ' because java does
 it that way' isn't a good enough one).  Chances are things are
 too coupled. 

Your reason is because you have a base class instantiating child
 classes, for most if not all its children.  Problem with that is
 you then need to modify that base class in about 4 places each
 time you add a child class. Very messy.

So how do you avoid modifying the base class?  Have an instance
 passed in, instead,  as Terry implied. 

Now you say you don't want the application code to have to import
 all of those child classes? There are several solutions to that, 

You can make a module which imports each of those, and stores a
 reference to each class.  That becomes the only place to modify
 as new ones are added. 

Or you can have each of these extra modules add its factory
 function to a common list or dict,  either at import time or in a
 once-called function.  That common list could be defined (with
 only the base class in it initially) in the module with the base

You could even add these methods you're trying to define to the
 base class, by defining them as ordinary functions in the
 corresponding module, and adding the appropriate attribute to the

Or you could have each new class add itself as a top level module
 attribute to the module you plan for your users to

Many more choices with various tradeoffs, and the best depends on
 a number of factors not yet discussed.  For example,  do all
 these classes take the same arguments to __init__?  If so, then a
 single factory that takes the class reference as a parameter
 might be useful.