Confused about class relationships
John O'Hagan
mail at johnohagan.com
Mon Dec 1 00:28:14 EST 2008
On Sat, 29 Nov 2008, Carl Banks wrote:
> On Nov 26, 11:20 pm, John O'Hagan <resea... at johnohagan.com> wrote:
[...]
> >
> > class Bar(list):
> >
> > def __init__(self, a_bar, args, engine):
> > list.__init__ (self, a_bar)
> > self[:] = a_bar
> > self.args = args
> > self.engine = engine
> > #more instance attributes...
> >
> > #methods...
> >
> > class Engine:
> >
> > def __init__(self, args):
> > self.args = args
> > #more instance attributes...
> >
> > def bar_builder(self):
> > #body of method generates lists...
> > yield Bar([generated_list], args, self)
> >
> > #more methods...
> >
> > #(other stuff...)
> >
> > def main(args):
> >
> > engine = Engine(args)
> > bars = engine.bar_builder()
> > for a_bar in bars:
> > #play the music!...
> >
> > While this works (to my surprise!) and solves the problem which motivated
> > it (i.e. Engine instances need to pass some attributes to Bar instances
> > ), it seems too convoluted. Should one class inherit the other?
>
> No. (I wonder if you meant, "Should one class reference the other?",
> as in, "Should Engines only reference bars or Bars only reference
> engines, but not both?", in which case the answer is a non-commital,
> "It depends.")
>
> Inheritance is not something you do because object A wants to access
> the attributes/properties/etc. of B. Actually, that is something that
> happens pretty often and when it does, there's a couple things you
> should think about:
>
> 1. How you want A to access the attributes of B. Should you just let
> A poke around in B, or should you define methods of B for A to call,
> and those methods access the internals of B? It's a judgment call
> most of the time.
>
> 2. Whether some behavior of B ought to be defined as part of A's class
> instead, or vice versa. There is sometimes ambiguity over what class
> a method that uses the attributes of two different objects should
> belong to.
>
> Inheritance isn't something you need to think about here.
>
> Inheritance is something you consider when you have two objects, A and
> B, that should act very similar or the same in certain situations.
> Engines and Bars don't seem to share any behavior at all. Contrast
> this to Bars and lists, which do share behavior. x[1] does pretty
> much the same thing whether x is a Bar or a list, I'd imagine, so
> there's reason for an inheritance relationship there.
>
> > If so, which way
> > around? Or is it fine as is?
>
> One thing you might want to consider is whether Engine instance could
> be simply passed into the Bar's play method (or whatever other method
> accesses the Engine attributes), and whether the Engine needs to be
> involved in generating bars at all. For instance:
>
>
> class Bar(list):
> def __init__(self, a_bar, args):
> list.__init__(self, a_bar)
> self[:] = a_bar
> self.args = args
> # etc.
> def play(self, engine):
> use(engine.time_signature).somehow()
> # instead of use(self.engine.time_signature).somehow()
>
>
> def bar_builder(self,args):
> # plain function, not part of Engine class
> # or perhaps a method of some other class
> yield Bar([generated_list],args)
>
>
> def main():
> engine = Engine(args)
> bars = bar_builder(self,args)
> for a_bar in bars:
> a_bar.play(engine)
>
>
> One benefit of doing it this way is that you've freed Bars and Engines
> from each other. Conceivably you could create a second engine object
> (maybe of a different type altogether), and play the very same Bar
> objects with that engine instead.
Thanks for such a detailed reply...I actually had bar_builder as a plain
function originally, but because I didn't know how to pass attributes around
like you have above, I was using globals to do it and was trying to solve
that by classing everything in sight. Although the program doesn't work quite
as you have deduced above, I can use the approach you suggest to simplify it
immensely. (I hope.)
>
> > I'm hoping this is a common trap I've fallen into; I just haven't been
> > able to get my head around it. (I'm a musician...)
>
> Well I think it looks pretty good for a musician newbie. There's a
> few organizational decisions I'd make differently, but overall it's
> clean and readable and not too complicated how you did it. At least
> not what you've showed us. :)
>
[...]
Believe me, the whole thing is more complicated and messy, but you don't want
to see my dirty laundry! :)
Regards,
john
More information about the Python-list
mailing list