Inheritance Question

Gabriel Genellina gagsl-py at yahoo.com.ar
Sat Nov 11 02:46:58 EST 2006


At Saturday 11/11/2006 03:31, Frank Millman wrote:

>Continuing your analogy of animals, assume a class A with a 'walk'
>method and an 'eat' method.
>
>Most animals walk the same way, but a few don't, so I create a subclass
>AW and override the walk method.
>
>Most animals eat the same way, but a few don't, so I create a subclass
>AE and override the eat method.
>
>How do I create an instance of an animal that both walks and eats
>differently?
>
>This is how I do it at present.
>
>class A(object):  # walks normally, eats normally
>     def walk(self):
>         normal walk
>     def eat(self):
>         normal eat
>
>class AW(A):  # walks differently, eats normally
>     def walk(self):
>         different walk
>
>class E(object):  # abstract class
>     def eat(self):
>         different eat
>
>class AE(E,A):  #  walks normally, eats differently
>     pass
>
>class AWE(E,AW):  #  walks differently, eats differently
>     pass
>
>So I use multiple inheritance instead of subclassing to override the
>eat method. It works, but it feels ugly. Is there a cleaner solution?

Answer 1) Move *both* ways of walk, and *both* ways of eating, to 
another base class. Best when this is pure behavior - no new 
attributes are involved.

class A(object):  # does not know how to walk, neither how to eat
     def walk(self):
         raise NotImplemented
     def eat(self):
         raise NotImplemented

class WalkNormallyCapability(object):  # knows how to walk normally
     def walk(self):
         normal walk

class WalkDifferentCapability(object):  # knows how to walk different
     def walk(self):
         different walk

class EatNormallyCapability(object):    # knows how to eat normally
     def eat(self):
         normal eat

class EatDifferentCapability(object):  # knows how to eat different
     def eat(self):
         different eat

class 
AWnEn(A,WalkNormallyCapability,EatNormallyCapability):  #  walks 
normally, eats normally
     pass

class 
AWdEn(A,WalkDifferentCapability,EatNormallyCapability):  #  walks 
different, eats normally
     pass
...etc.

The xxxCapability classes are usually referred as "mixin class" - 
they add a new capability to an existing class, without adding new 
attributes (they could, but initialization gets more complicated, you 
must rewrite __init__ and so...). They may inherit from a common base 
class, too, but that's not required in Python.


Answer 2) Use an instance of another class to define how to walk and 
how to eat. Advantage: it can later be modified at runtime (strategy pattern).

class A(object):
     def __init__(self, walker, eater):
         self.walker=walker
         self.eater=eater
     def walk(self):
         self.walker.walk()
     def eat(self):
         self.eater.eat()

class NormalWalker(object):  # knows how to walk normally
     def walk(self):
         normal walk

class DifferentWalker(object):  # knows how to walk different
     def walk(self):
         different walk

class NormalEater(object):    # knows how to eat normally
     def eat(self):
         normal eat

class DifferentEater(object):  # knows how to eat different
     def eat(self):
         different eat

a=A(NormalWalker(), DifferentEater())
or define a factory function when you decide which walker an which 
eater to use based on its arguments. As above, they may inherit from 
a common base class (Walker, Eater, by example).



-- 
Gabriel Genellina
Softlab SRL 

__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam ¡gratis! 
¡Abrí tu cuenta ya! - http://correo.yahoo.com.ar



More information about the Python-list mailing list