On Nov 15, 3:28 pm, "[EMAIL PROTECTED]" <[EMAIL PROTECTED]> wrote: >
My response ended up being pretty long and heavy for a beginner, but you sound pretty smart. > In learning about design patterns, I've seen discussion about using > inheritance when an object's relationship to another object is 'is-a' > and composition when the relationship is 'has-a'. I've never been a big fan of this rule, for two reasons. First of all, "is a" and "has a" aren't always used in the sense intended by this rule's inventor. To illustrate the confusion, take your Pet-Owner example. When you say "A Pet has an Owner", the verb "to have" has the sense of "to possess". But possession alone is *not* the right sense of "to have" to suggest using containment. (Note: I'm using containment to mean "object X owns object Y". Referencing the object without owning it is not containment; it's just referencing.) The reciprocal relationship to "has a" is "is a part of", and I rather prefer that way of putting it. The Pet has an Owner, but the Owner is not part of the Pet, so "has a" is being used in the wrong sense. OTOH, a Car has an Engine, and an Engine is part of a Car, so "has a" is being used in the right sense there. This is not to say containment is not the appropriate way to implement Pet-Owner in any case. If this program is Pet-centric, and the Owner exists only insofar as it is perceived by the Pet, containment might be right way. That's another point: sometimes external circumstances play a part in whether inheritance or containment or something else should be used. FWIW, my first stab at a Pet-Owner relationship would probably look something like this: class Family: def __init__(self,humans,pets): self.humans = humans self.pets = pets Note that a Family has Pets, and Pets are part of the Family, so containment would be a good idea for Family-Pet relationship. (The Pets and Humans would have a field referring back to the Family, and the pet could determine its owners that way.) A source of confusion with "is a" is that it doesn't necessarily imply a good inheritance relationship (aka Liskov substitutability). Consider a Rectangle class that has methods set_width() and set_height(). Should Square class inherit from Rectangle? A Square is a Rectangle, but it's not suitable as a subclass of Rectangle, because the width and height can't be set independently. You can't substitute a Square for a Rectangle and get reasonable behavior. Second reason I don't like "is a" and "has a": They are misleading enough for concrete objects like Pets, Owners, Rectangles, and so on. But real programming is often done with abstract objects like SimulationContexts, EncryptedHTTPConnections, ItemSequencers, and FingerProtocols. "Is-a" and "has-a" relationships are not always clear for classes such as these. > Also, I've seen talk that ideally you shouldn't have too many "dots" > in your method calls, instead using delegates to the methods and > attributes. Can anyone elaborate on this? Ideally, should I be writing > getattr() methods so I can do pet.address instead of > pet.owner.address? Should I be doing the same with owner's methods > like I did with get_foo()? I wouldn't worry about minimizing dots. If you find yourself often using a certain long expressions like self.owner.house.yard.grass_length you might want to delegate them on a case-by-case basis by writing methods like this: def get_home_grass_length(self): return self.owner.house.yard.grass_length But using getattr to do it automatically is tricky, error prone, and defeats the purpose of keeping seperate namespaces. OTOH, if you find yourself delving several dots deep a lot, it suggests that you need to refactor you code. Move some of the code from the shallower classes into the deeper classes, closer to the data it needs. Hope this helped and didn't confuse you even more. :) Good luck learning. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list