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'
Now I can set up the following concrete classes -
class ClassA1(ClassA):
def __init__(self):
ClassA.__init__(self)
class ClassA2(Class2,ClassA):
def __init__(self):
ClassA.__init__(self)
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, and I
believe it is not even supported in some languages. Can anyone suggest
a better way of tackling this problem?
Thanks
Frank Millman 10 1176
Frank Millman, just a short note, more expert people can give you
better answers. There aren't abstract classes in Python. They are all
concrete. You may have classes with undefined methods (they may raise
NotImplementedError).
Multiple inheritance isn't supported by Java and Ruby, but it is
supported by C++ and Python, so you can use it in Python.
There are also ways of mixing methods. You may define methods, and then
lists of methods to add to your classes.
Bye,
bearophile be************@lycos.com wrote:
Frank Millman, just a short note, more expert people can give you
better answers. There aren't abstract classes in Python. They are all
concrete. You may have classes with undefined methods (they may raise
NotImplementedError).
Multiple inheritance isn't supported by Java and Ruby, but it is
supported by C++ and Python, so you can use it in Python.
There are also ways of mixing methods. You may define methods, and then
lists of methods to add to your classes.
Bye,
bearophile
I use the term 'abstract class' in the abstract sense :-)
Say I have three classes where 90% of the attributes and methods are
common. It makes sense to create a base class with these attributes and
methods, and turn each of the three classes into a subclass which
inherits from the base class and overrides the bits that are unique to
each one.
This is what I call an abstract class. Maybe there is a more correct
term.
Frank
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 'o****@xiludom.gro'.split('@')])"
Bruno Desthuilliers wrote:
Frank Millman wrote:
be************@lycos.com wrote:
There aren't abstract classes in Python. They are all
concrete.
(snip)
I use the term 'abstract class' in the abstract sense :-)
Say I have three classes where 90% of the attributes and methods are
common. It makes sense to create a base class with these attributes and
methods, and turn each of the three classes into a subclass which
inherits from the base class and overrides the bits that are unique to
each one.
This is what I call an abstract class. Maybe there is a more correct
term.
Depends if instanciating this base class would make any sense.
It would not make sense, no.
I have not gone to the trouble of raising NotImplementedError - the
methods that the subclasses *must* override just have a 'pass'
statement. I guess it would be more correct to raise the error, as it
would give me a quicker indication of an error if I happened to omit
one, but in practice I would find out pretty quickly anyway.
Frank
Le vendredi 08 septembre 2006 09:51, be************@lycos.com a écrit*:
Frank Millman, just a short note, more expert people can give you
better answers. There aren't abstract classes in Python. They are all
concrete.
Really ? This is like saying there is no singleton in Python...
class AbstractClass(object) :
def __init__(self) : raise RuntimeError('Ths class is an abstract one !')
The abstract class can then define APIs (methods which raise
NotImplementedError) and/or logic (fully implemented methods).
With this scheme you are not stuck to the "API only" usage of abstract classes
like in Java nad its interfaces.
You may have classes with undefined methods (they may raise
NotImplementedError).
C++ "pure virtual methods" is only the C++ way of doing something which is a
more general concept in OOP.
--
_____________
Maric Michaud
_____________
Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Le vendredi 08 septembre 2006 10:15, Bruno Desthuilliers a écrit*:
You
mentioned NotImplementedError, which is indeed the usual way to make
something "abstract" in Python.
Hummm, some more thoughts about this.
I can imagine class hierarchies where the presence of not implemented methods
doesn't mean that the class is actually an abstract one. Even if partial
implementation is not a common scheme it can save you from writing a lot of
classes.
For example :
class car : #abstract
def accelerate() : raise NotimplementedError
def getBaseBuildPrice() : raise NotimplementedError
def getOptionsPrice() : raise NotimplementedError
def getPublicPrice() : raise NotimplementedError
class SerieA(car) :
"""abstract, it's before the car
get out of the factory"""
def accelerate() : ...
def getBaseBuildPrice() : ...
class CrashTestVendorSerieA(SerieA) :
"""concrete, but doesn't
implement getPublicPrice"""
def getOptionsPrice() : ...
class CommercialSerieA(SerieA) :
def getOptionsPrice() : ...
def getPublicPrice() : ....
Doing the same with more traditional object design give :
class car : #abstract
def accelerate() : raise NotimplementedError
def getBaseBuildPrice() : raise NotimplementedError
class SerialCar : #abstract
def getOptionsPrice() : raise NotimplementedError
class ComercialCar : #abstract
def getPublicPrice() : raise NotimplementedError
class SerieA(car, SeriialCar) : #abstract
def accelerate() : ...
def getBaseBuildPrice() : ...
class CrashTestVendorSerieA(SerieA) : # concrete
def getOptionsPrice() : ...
class CommercialSerieA(SerieA, CommercialCar) : # concrete
def getOptionsPrice() : ...
def getPublicPrice() : ...
And this can become a true spider net for more complicated cases. Obviously,
in practice we will choose alternatives to inheritance (strategies,
visitors, ...) to work with such complex situations, but it seems to me that
partial implementation is not a bad choice, specifically in regard to duck
typing.
--
_____________
Maric Michaud
_____________
Aristote - www.aristote.info
3 place des tapis
69004 Lyon
Tel: +33 426 880 097
Frank Millman wrote:
Bruno Desthuilliers wrote:
>Frank Millman wrote:
>>be************@lycos.com wrote: There aren't abstract classes in Python. They are all concrete.
(snip)
>>I use the term 'abstract class' in the abstract sense :-)
Say I have three classes where 90% of the attributes and methods are common. It makes sense to create a base class with these attributes and methods, and turn each of the three classes into a subclass which inherits from the base class and overrides the bits that are unique to each one.
This is what I call an abstract class. Maybe there is a more correct term.
Depends if instanciating this base class would make any sense.
It would not make sense, no.
I have not gone to the trouble of raising NotImplementedError - the
methods that the subclasses *must* override just have a 'pass'
statement. I guess it would be more correct to raise the error, as it
would give me a quicker indication of an error if I happened to omit
one, but in practice I would find out pretty quickly anyway.
Mmm... My own experience is that methods that *must* be redefined are
better raising NotImplementedError. Makes things more obvious IMHO.
Now there are of course methods that are only provided as hooks - here
it's ok to have some no-op default behaviour.
My 2 cents
Frank
--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Bruno Desthuilliers wrote:
Frank Millman wrote:
I have not gone to the trouble of raising NotImplementedError - the
methods that the subclasses *must* override just have a 'pass'
statement. I guess it would be more correct to raise the error, as it
would give me a quicker indication of an error if I happened to omit
one, but in practice I would find out pretty quickly anyway.
Mmm... My own experience is that methods that *must* be redefined are
better raising NotImplementedError. Makes things more obvious IMHO.
Can't argue with that. I have just gone through my app and changed them
all :-)
Frank
Frank Millman wrote:
Bruno Desthuilliers wrote:
>>Frank Millman wrote:
>>>I have not gone to the trouble of raising NotImplementedError - the methods that the subclasses *must* override just have a 'pass' statement. I guess it would be more correct to raise the error, as it would give me a quicker indication of an error if I happened to omit one, but in practice I would find out pretty quickly anyway.
Mmm... My own experience is that methods that *must* be redefined are better raising NotImplementedError. Makes things more obvious IMHO.
Can't argue with that. I have just gone through my app and changed them
all :-)
Yup, if a thing can't go wrong, it won't
regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden
Maric Michaud a écrit :
Le vendredi 08 septembre 2006 10:15, Bruno Desthuilliers a écrit :
>>You mentioned NotImplementedError, which is indeed the usual way to make something "abstract" in Python.
Hummm, some more thoughts about this.
I can imagine class hierarchies where the presence of not implemented methods
doesn't mean that the class is actually an abstract one.
I can imagine this too - as well as I can imagine the nightmarish
spaghetti code that could use this class hierarchie.
Even if partial
implementation is not a common scheme it can save you from writing a lot of
classes.
A partial implementation should return default values, not raise (aka
NullObjectPattern). Well, IMHO at least.
(snip)
And this can become a true spider net for more complicated cases. Obviously,
in practice we will choose alternatives to inheritance (strategies,
visitors, ...)
Composition/delegation...
to work with such complex situations,
Indeed. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: BJörn Lindqvist |
last post by:
A problem I have occured recently is that I want to subclass builtin
types. Especially subclassing list is very troublesome to me. But I
can't find the right syntax to use. Take for example this...
|
by: Brent |
last post by:
I'd like to subclass the built-in str type. For example:
--
class MyString(str):
def __init__(self, txt, data):
super(MyString,self).__init__(txt)
self.data = data
|
by: Guinness Mann |
last post by:
I have a class that I use throughout my application, and I store
collections of my class in an ArrayList. To avoid some really ugly
casting I'd like to subclass ArrayList to get a typed version.
...
|
by: Peter Oliphant |
last post by:
I just discovered that the ImageList class can't be inherited. Why? What
could go wrong? I can invision a case where someone would like to add, say,
an ID field to an ImageList, possible so that...
|
by: D |
last post by:
I have a client application that I want (behind the scenes) to check
and make sure a remote host is up (i.e. by ping or TCP connect). I'm
assuming that, since I want this to go on "unknowingly" to...
|
by: Jackson |
last post by:
I've got an inheritance question and was hoping brighter minds could
guide me. I am in the strange situation where some of the methods in a
subclass are actually more general than methods in a...
|
by: arncota |
last post by:
Hi,
I created a UserControl, and created its UI with the designer. Next,
I wanted to create a subclass of that UserControl, with a new UI. But
when I open it in the designer, I see the UI...
|
by: manatlan |
last post by:
I've got an instance of a class, ex :
b=gtk.Button()
I'd like to add methods and attributes to my instance "b".
I know it's possible by hacking "b" with setattr() methods. But i'd
like to do...
|
by: Ray |
last post by:
Hi all,
I am thinking of subclassing the standard string class so I can do
something like:
mystring str;
....
str.toLower ();
A quick search on this newsgroup has found messages by others
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: aa123db |
last post by:
Variable and constants
Use var or let for variables and const fror constants.
Var foo ='bar';
Let foo ='bar';const baz ='bar';
Functions
function $name$ ($parameters$) {
}
...
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: ryjfgjl |
last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
| |