Designing for Inheritance

Luigi Ballabio ballabio at mac.com
Wed Dec 12 06:43:34 EST 2001


At 09:42 AM 12/12/01 +0000, nspies.geo wrote:
>Hi all,
>The problem is thus: how do I design the base class so that it will
>create an extracted object of the correct type, even if it's been
>inherited?  It may well be that the inherited class needs to wrap the
>base class function, but I do not wish to re-write the function in
>every base class.
>
>Here it is in code.
>
>class BaseAlignment:
>    def extractx(self, x):
>       extraction = BaseAlignment()
>       extraction = self.data[0:x]
>
>       return extraction

You have a problem here. Python does not have the copy semantics of C, 
i.e., you are not even returning a BaseAlignment here. What happens is:

extraction = BaseAlignment() # here a temporary object of class
                              # BaseAlignment is created. The
                              # reference "extraction" points to it.

extraction = self.data[0:x]  # here the reference "extraction" is relinked
                              # to the slice returned from self.data.
                              # The temporary BaseAlignment() has no more
                              # refs pointing to it and is garbage-collected.
                              # The previous statement had no effect at all
                              # and could be removed!

return extraction            # here you return the slice (a list or a tuple
                              # depending on the type of self.data)

In short, the above is perfectly equivalent to

class BaseAlignment:
     def extractx(self,x):
         return self.data[0:x]

If I interpret right what you want, you might try this instead:

class BaseAlignment:
     def __init__(self,data):
         # initialize the data with the passed list
         self.data = data
     def extractx(self,x):
         # self.__class__ returns the right class, i.e., the right constructor
         # we use it to return an object of the right type initialized with
         # the desired data
         return self.__class__(self.data[0:x])

class InheritedAlignment(BaseAlignment):
     # do not define the constructor---it will be inherited
     def extractx(self,x):
         obj = BaseAlignment.extractx(self,x)
         obj.message = "Hello world"
         return obj

This is what happens in Python 2.1.1:

 >>> b = BaseAlignment([1,2,3,4])
 >>> extr = b.extractx(2)
 >>> extr.__class__
<class test.BaseAlignment at 007CD50C>
 >>> extr.data
[1, 2]
 >>> d = InheritedAlignment([1,2,3,4])
 >>> extr2 = d.extractx(2)
 >>> extr2.__class__
<class test.InheritedAlignment at 007CAAAC>
 >>> extr2.data
[1, 2]
 >>> extr2.message
'Hello world'
 >>>

Hope this helped,
                         Luigi





More information about the Python-list mailing list