6

In many langauges, super() lets you call the parent method which you have overridden. I've been using super in my Javascript (with fake object oriented implementation) to run common code for a long time without problems. Now I've finally hit a case where calling a protected base class method would have been better than calling super.

Here's a concrete example.

Grandparent -> Parent -> Kid

I needed to add a Kid. It's identical to Parent except for one method called someMethod. Kid's someMethod needed to do Grandparent's common stuff, but not Parent's specific stuff. So Kid's someMethod could not call super because that would trigger Parent specific code. Instead of changing my grand class structure, I just made Kid duplicate Grandparent's common code.

Grandparent {
 someMethod {
  do common stuff
 };
}

Parent: Grandparent {
 someMethod {
  super();
  do parent specific stuff
 }
}

Kid: Parent {
 someMethod {
  duplicate of common stuff
  do kid specific stuff 
 }
}

In my book, duplicate code is bad. If only Grandparent wrote its common stuff as a protected method, I wouldn't need to duplicate code.

Grandparent {
 protected commonMethod
 virtual someMethod
}

Parent: Grandparent {
 someMethod {
  commonMethod
  do parent specific stuff
 }
}

Kid: Parent {
 someMethod {
  commonMethod
  do kid specific stuff
 }
} 

Should I just completely stop using super and switch to protected methods for running common code? Are there any pitfalls to protected methods for running common stuff?

1 Answer 1

15

No, you shouldn't stop using super, you should stop implementing bad OO designs.

Notwithstanding the fact that we're not talking about true inheritance, why are you inheriting from the parent if you don't want its functionality? You're breaking the abstraction. The leaf-level class shouldn't know anything about the actual implementation of the parent, certainly not enough to know that it doesn't want the "parent specific stuff" to be done.

More generally, you should be honouring the Liskov Substitution Principle whenever possible and only creating derived types that can actually be substituted wholesale for the base types. This seems to have been violated here; the parent has altered the contract of the grandparent in such a way that further generations of descendants have to disable it in order to function correctly.

As far as I can tell, your kid should be a descendant of grandparent.

Separately:

  • There are other ways to avoid duplication. Not everything has to be based on inheritance; composition and plain old referencing are just fine. Make sure you're not violating the SRP.

  • At least in most OO implementations, protected and virtual are not mutually exclusive. An override method is still free to call protected methods of its base, so if you foresee a need for derived classes to use specific functionality of the base, then abstract it into a protected method. That has absolutely no bearing on whether or not another method should be virtual.

I think the root of the problem really lies in this sentence:

I've been using super in my Javascript... to run common code

Inheritance is not primarily a tool for code reuse. It's a tool for... well, inheritance, i.e. when you need to be able to substitute one implementation for another without loss of fidelity (polymorphism) or when the base class won't have all the information it needs to execute a particular operation and it needs to be able to delegate this to a derived class (abstraction).

If you're using inheritance for the sole purpose of jamming in code that's frequently used, then you've completely misunderstood the concept; use composition for that, or hell, just write a bunch of functions. There's no reason to try to fake inheritance when the best possible result is still inferior to simpler alternatives.

5
  • +1 esp. for "There's no reason to try to fake inheritance when the best possible result is still inferior to simpler alternatives." although would perhaps benefit from mention of LSP May 17, 2011 at 22:50
  • @Rein - thanks, I was fishing around in this junkyard I call a memory and couldn't locate the formal name. That's what I was looking for.
    – Aaronaught
    May 17, 2011 at 22:54
  • One of the best answers I have ever read.
    – Gratzy
    May 17, 2011 at 23:34
  • My Kid inherits from Parent because Kid reacts the same as Parent except for one method: someMethod. If Kid had inherited from Grandparent, it would have to copy and paste all but one method from Parent.
    – JoJo
    May 18, 2011 at 7:04
  • @JoJo: This is still a problem that could be solved by composition. Or perhaps it's simply a badly-designed method. Without far more detailed specifics, it's hard to know how to resolve the design flaw, but it is a design flaw.
    – Aaronaught
    May 18, 2011 at 22:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.