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
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
andvirtual
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.
-
+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 LSPRein Henrichs– Rein Henrichs2011年05月17日 22:50:55 +00:00Commented 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– Aaronaught2011年05月17日 22:54:55 +00:00Commented May 17, 2011 at 22:54
-
One of the best answers I have ever read.Gratzy– Gratzy2011年05月17日 23:34:46 +00:00Commented May 17, 2011 at 23:34
-
My
Kid
inherits fromParent
becauseKid
reacts the same asParent
except for one method:someMethod
. IfKid
had inherited fromGrandparent
, it would have to copy and paste all but one method fromParent
.JoJo– JoJo2011年05月18日 07:04:19 +00:00Commented 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– Aaronaught2011年05月18日 22:31:48 +00:00Commented May 18, 2011 at 22:31