Question about subclassing - version 2

Bruno Desthuilliers onurb at xiludom.gro
Fri Sep 8 10:34:29 CEST 2006

Frank Millman wrote:
> Hi all
> I recently posted a question about subclassing. I did not explain my
> full requirement very clearly, and my proposed solution was not pretty.
> I will attempt to explain what I am trying to do more fully, and
> describe a possible solution. It is still not pretty, so I would
> appreciate any comments.
> I have a base class (ClassA), which is an abstract class. Most of the
> methods and attributes are common to all subclasses, so there is not
> much they have to override.
> I have a subclass (ClassB) of my base class, which is also abstract. It
> represents a subset of ClassA, and overrides some of its methods. When
> I create a concrete class (is that the correct term?) I subclass either
> from ClassA or from ClassB.
> Now I want to represent a different subset of ClassA, which overrides
> some of its methods. This subset can apply to ClassB as well as to
> ClassA.
> In pseudo terms, I want ClassA1, ClassA2, ClassB1, and ClassB2 where A1
> is the base class, B overides some methods, and 2 overrides other
> methods, and I want to subclass from any of them.
> My original solution involved passing 1 or 2 as an argument, and
> putting some code into __init__ which redefined certain methods if it
> received a 2. This worked, but it meant that I could not then easily
> redefine the method again in a concrete class.
> My new idea is to use multiple inheritance. This is how it would work.
> class ClassA(object):
>     def __init__(self):
>         pass
>     def test1(self):
>         print 'Base method 1'
>     def test2(self):
>         print 'Base method 2'
> class ClassB(ClassA):
>     def __init__(self):
>         ClassA.__init__(self)
>     def test1(self):
>         print 'Overriding method 1'
> class Class2(object):
>     def test2(self):
>         print 'Overriding method 2'

To be pedantic, Class2.test2 is not overridding anything, since there's
no "test2" method in it's parent class.

> Now I can set up the following concrete classes -
> class ClassA1(ClassA):
>     def __init__(self):
>         ClassA.__init__(self)

If that's the only thing you do in the __init__, then don't bother write
an init method at all.

> class ClassA2(Class2,ClassA):
>     def __init__(self):
>         ClassA.__init__(self)

May I suggest having a look at super() ?

> class ClassB1(ClassB):
>     def __init__(self):
>         ClassB.__init__(self)
> class ClassB2(Class2,ClassB):
>     def __init__(self):
>         ClassB.__init__(self)
> Now if I do the following, I get the results shown, which is what I
> want -
> ClassA1().test1() - 'Base method 1'
> ClassA1().test2() - 'Base method 2'
> ClassB1().test1() - 'Overriding method 1'
> ClassB1().test2() - 'Base method 2'
> ClassA2().test1() - 'Base method 1'
> ClassA2().test2() - 'Overriding method 2'
> ClassB2().test1() - 'Overriding method 1'
> ClassB2().test2() - 'Overriding method 2'
> Now for the real test -
> class ClassC3(Class2,ClassB):
>     def __init__(self):
>        ClassB.__init__(self)
>     def test1(self):
>         print 'Overriding method 1 from ClassC3'
>     def test2(self):
>         print 'Overriding method 2 from ClassC3'
> ClassC3().test1() - 'Overriding method 1 from ClassC3'
> ClassC3().test2() - 'Overriding method 2 from ClassC3'
> So it works. However, using multiple inheritance is not ideal,

Why so ? Multiple inheritence is a pretty useful tool - but it can
become tricky very soon. IMHO, it's best use is for mixin classes...

> and I
> believe it is not even supported in some languages.

A lot of things aren't even supported in some languages !-)

> Can anyone suggest
> a better way of tackling this problem?

Not out of my hat. Just a few considerations on Python and OO: Python
being dynamically typed, inheritence is only about sharing
implementation. There's another way to do share implementation -
composition/delegation. It's more flexible, and can avoid "cartesian
product" multiplication of classes. It's also less advertised than
inheritance - probably because of "some languages" that fail to offer
any support for it. The good news here is that Python makes it a breeze,
thanks to the __getattr__/__setattr__ hooks. Now I don't know if it
makes any sense WRT/ your current problem...

bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"

More information about the Python-list mailing list