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 '[EMAIL PROTECTED]'.split('@')])" -- http://mail.python.org/mailman/listinfo/python-list