ke...@kendy.org wrote:
Hello

I'm new to classes. And I hope the my question isn't too big.

I have electronic test equipment, but thought that a boat example
would be easier. Can you help me untangle my class design?
My problem is basically multiple inheritance, but I want to be
flexible for how many will inherit.

Your first problem is that you are misusing inheritance when you should be using composition instead.

Inheritance is for "is-a" relationships. For example:

Bob is a Person, so Bob should be an instance of Person class.

A Person is a Mammal, so Person should inherit from Mammal class.

A Mammal is an Animal, so Mammal should inherit from Animal class.


Bob has a wallet, he is not a wallet himself. So the Bob instance should have an attribute "wallet", storing an instance of Wallet class. This is called composition.

In your example, you have a Boat class. Boat is pretty generic, so it might be the top-level class. Or it might be a subclass of Vehicle. You might then subclass Boat to give SailingBoat, MotorBoat, SpeedBoat, Battleship, etc.

But boats are not kinds of engines, so it is inappropriate for Boat to inherit from Engine. A boat (well, at least some boats) has an engine, so you might do something like this:


class Boat:
    pass

class SailBoat(Boat):
    def __init__(self, sails):
        self.sails = sails

class RowBoat(Boat):
    def __init__(self, oars):
        self.oars = oars

class PowerBoat(Boat):
    def __init__(self, engine):
        self.engine = engine

class SpeedBoat(PowerBoat):
    """A SpeedBoat is a kind of PowerBoat with an outboard motor."""
    def __init__(self):
        super(SpeedBoat, self).__init__(outboard_motor)

class Yacht(SailBoat):
    """A Yacht is a kind of SailBoat."""
    # Note that the name Yacht is ambiguous, as it is also used for
    # a class of small power boats!
    def __init__(self):
        super(SailBoat, self).__init__(spinnaker)




A boat with both sails and an engine would then use multiple inheritance to inherit from both PowerBoat and SailBoat; it would have both an engine and a sail.

Note that when using single-inheritance, you have a choice in how to call the parent classes' method:

class K(C):
    def method(self, arg):
        result = C.method(self, arg)  # Call the parent method directly.
        process(result)

or use super:

class K(C):
    def method(self, arg):
        result = super(K, self).method(arg)  # Let Python find the method.
        process(result)


Either way is fine.

BUT once you intend to use multiple inheritance, you MUST use super, or your code risks being buggy. NEVER call a superclass method directly using multiple inheritance, or even if you might someday want to use multiple inheritance. Always use super instead.

(Note: in Python 3, you can simplify the call to super to just super() instead of super(K, self). This does not work in Python 2.)

Multiple inheritance is quite tricky to get right, which is why many programming languages prohibit it. If you google for "multiple inheritance python" you will find many discussions about it, explaining the pros and cons, difficulties and alternatives.


One last thing: you will save yourself a lot of pain in the future if you stick to a consistent convention for naming things. The usual convention used in Python is the classes are named with an initial Capital letter, using so-called "CamelCase" if the name has multiple words. Methods, functions, attributes and instances are named in lowercase, using underscores to separate words: bob_the_builder = Builder(name='Bob').

For more about the suggested (but not compulsory) naming conventions, see this:

http://www.python.org/dev/peps/pep-0008/



--
Steven
_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to