4 ms·
> You're describing a fairly narrow subset of subclassing; notably one that is (as you point out) almost equivalent to composition. I'm not sure why you say th
by jdlshore 13y ago
> You're describing a fairly narrow subset of subclassing; notably one that is (as you point out) almost equivalent to composition.
I'm not sure why you say this is a narrow subset. I'm describing a way of thinking about inheritance (inheritance is like composition + automatic delegation). That way of thinking can be applied to any subclassing operation, and I think it's instructional to do so. It can help you see what's a good idea and what's not.
Let's run down the list. Assume you have a class A with a method foo() and class B with method bar().
The equivalent* of "A extends B" is:
function A() {
this._b = new B(); // equivalent* to calling superclass constructor
}
A.prototype.bar = function() {
return this._b.bar(); // manually delegate
}
Now let's say A accesses its superclass's private variables in order to do something. The equivalent* is:
A.prototype.foo = function() {
return this._b._privateVar * 2; // obviously bad, don't do that!
}
You wouldn't access the private variables of an object you compose; it's obviously bad form. Don't do it when you inherit, either.
Now let's talk overriding the superclass's methods. There are several different ways you could do that. The equivalents* are:
// Replace superclass method
A.prototype.bar = function() {
return "my own thing"; // obviously fine
}
// Replace superclass method and access superclass state directly
A.prototype.bar = function() {
return this._b._privateVar * 2; // obviously bad, don't do that!
}
// Extend superclass method
A.prototype.bar = function() {
var result = this._b.bar(); // equivalent* to calling superclass method
return result * 2; // perfectly okay
}
// Extend superclass method and access superclass state directly
A.prototype.bar = function() {
var result = this._b.bar(); // equivalent* to calling superclass method
return result * this._b._privateVar; // obviously bad, don't do that!
}
Don't access the private variables of your superclass (or objects you compose) and you'll be fine. Sure, you'll be in trouble if the superclass changes the semantics of the parent method, but that's true of all functions everywhere. If the semantics of a function you're using changes, your code probably just broke. It doesn't matter if the function is defined in a superclass or not.
The one thing that's unique to inheritance is the idea of semi-private ("protected") methods that are only visible to subclasses. I agree that they're something to be used sparingly, but they're no different than any other superclass method in how they should be used and overridden. It's a moot point, though, because JS doesn't have them.
*Not exactly equivalent, but close enough for these examples.
- emn13 13y agoI think protected methods are just a bad idea in every case. They don't really offer protection (because a subclass can expose them) and they prevent other forms of composition even where they're more appropriate. If you're open to inheritance, you're necessarily open to composition - making that messy serves no purpose. As to this example: // Replace superclass method A.prototype.bar = function() { return "my own thing"; // obviously fine } This is NOT fine - it's really quite nasty. You're breaking encapsulation by affecting how the internals of B work - calls from B's code to bar() will now fail to work as expected. What you want is to use your bar to outside code, but not affect the encapsulation of the superclass. And note that none of this mitigates the pit-of-complexity that inheritance encourages as described in the post you replied to (i.e. bloated, hard-to-wrap API's). There are inheritance-like techniques that work better and don't have the downsides.
- jdlshore 13y agoI don't agree, but I'm going to let it drop. I just wanted to reply to say "thanks" for engaging in a thoughtful conversation. Somebody's been downvoting thoughtful posts like yours (because they disagree with them, I guess). I wish they'd stop and I wanted to let you know it wasn't me. :-)
- emn13 13y agoHey, thanks for the friendly sign off! A much nicer way to end a conversation. Given the subtly of these issues (what is the right design of such an artificial construct), I guess the only obvious thing is that there's no obviously right answer - let alone that it's easy to explain the pros+contras in a reasonable amount of time on an online forum such as this :-).