Skipping a superclass

Discussion in 'Python' started by Steven D'Aprano, Aug 2, 2009.

  1. I have a series of subclasses like this:

    class A(object):
    def method(self, *args):
    print "Lots of work gets done here in the base class"

    class B(A):
    def method(self, *args):
    print "A little bit of work gets done in B"
    super(B, self).method(*args)

    class C(B):
    def method(self, *args):
    print "A little bit of work gets done in C"
    super(C, self).method(*args)


    However, the work done in C.method() makes the work done in B.method()
    obsolete: I want one to run, or the other, but not both. C does need to
    inherit from B, for the sake of the other methods, so I want C.method()
    *only* to skip B while still inheriting from A. (All other methods have
    to inherit from B as normal.)

    So what I have done is change the call to super in C to super(B, self)
    instead of super(C, self). It seems to work, but is this safe to do? Or
    are there strange side-effects I haven't seen yet?



    --
    Steven
     
    Steven D'Aprano, Aug 2, 2009
    #1
    1. Advertising

  2. Steven D'Aprano

    Chris Rebert Guest

    On Sun, Aug 2, 2009 at 5:36 AM, Steven
    D'Aprano<> wrote:
    > I have a series of subclasses like this:
    >
    > class A(object):
    >    def method(self, *args):
    >        print "Lots of work gets done here in the base class"
    >
    > class B(A):
    >    def method(self, *args):
    >        print "A little bit of work gets done in B"
    >        super(B, self).method(*args)
    >
    > class C(B):
    >    def method(self, *args):
    >        print "A little bit of work gets done in C"
    >        super(C, self).method(*args)
    >
    >
    > However, the work done in C.method() makes the work done in B.method()
    > obsolete: I want one to run, or the other, but not both. C does need to
    > inherit from B, for the sake of the other methods, so I want C.method()
    > *only* to skip B while still inheriting from A. (All other methods have
    > to inherit from B as normal.)
    >
    > So what I have done is change the call to super in C to super(B, self)
    > instead of super(C, self). It seems to work, but is this safe to do? Or
    > are there strange side-effects I haven't seen yet?


    Barring some true weirdness in super(), I don't /think/ so. It
    obviously works fine in the single-inheritance case, and (after some
    brute-force testing) the only permitted multiple inheritances
    involving C and (A or B) always have C ahead of B in the MRO (method
    resolution order).

    The fact that you're wanting to bypass a superclass method might
    suggest however, that your hierarchy could be structured better. Have
    you considered moving B.method() into another, new class (e.g. newB)
    which subclasses B? Then C can inherit from B without inheriting the
    unwanted method, while B's functionality still exists, just under a
    new name (newB).

    Cheers,
    Chris
    --
    http://blog.rebertia.com
     
    Chris Rebert, Aug 2, 2009
    #2
    1. Advertising

  3. On Aug 2, 2009, at 5:36 AM, Steven D'Aprano wrote:
    > I have a series of subclasses like this:
    >
    > class A(object):
    > def method(self, *args):
    > print "Lots of work gets done here in the base class"
    >
    > class B(A):
    > def method(self, *args):
    > print "A little bit of work gets done in B"
    > super(B, self).method(*args)
    >
    > class C(B):
    > def method(self, *args):
    > print "A little bit of work gets done in C"
    > super(C, self).method(*args)
    >
    >
    > However, the work done in C.method() makes the work done in B.method()
    > obsolete: I want one to run, or the other, but not both. C does need
    > to
    > inherit from B, for the sake of the other methods, so I want
    > C.method()
    > *only* to skip B while still inheriting from A. (All other methods
    > have
    > to inherit from B as normal.)


    This might not be applicable to the larger problem you're trying to
    solve, but for this sample, I would write it as:

    class A(object):
    def method(self, *args):
    self._method(*args)
    print "Lots of work gets done here in the base class"
    def _method(self, *args):
    pass # or perhaps raise NotImplemented

    class B(A):
    def _method(self, *args):
    print "A little bit of work gets done in B"

    class C(B):
    def _method(self, *args):
    print "A little bit of work gets done in C"

    > So what I have done is change the call to super in C to super(B, self)
    > instead of super(C, self). It seems to work, but is this safe to do?
    > Or
    > are there strange side-effects I haven't seen yet?


    In a diamond-inheritance situation, you may end up skipping methods
    besides just B.method().

    -Miles
     
    Miles Kaufmann, Aug 3, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris Vidal
    Replies:
    3
    Views:
    2,222
  2. Tommy Martin

    Forms Authentication and skipping a page

    Tommy Martin, Dec 15, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    339
    Tommy Martin
    Dec 15, 2003
  3. branton ellerbee

    sqlDataReader skipping first row in loop

    branton ellerbee, Jun 2, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    6,343
    Teemu Keiski
    Jun 2, 2004
  4. Evan Klitzke
    Replies:
    0
    Views:
    374
    Evan Klitzke
    Aug 2, 2007
  5. bart van deenen
    Replies:
    6
    Views:
    786
    bart van deenen
    Mar 3, 2009
Loading...

Share This Page