4 ms·
Good article, but I think the real message isn't to not use inheritance, but to use with great care. Inheritance gives you a great characteristic -- isa relati
by kenjackson 13y ago
Good article, but I think the real message isn't to not use inheritance, but to use with great care.
Inheritance gives you a great characteristic -- isa relationships. And this is something you don't get with composition.
That said, the fragility with poorly constructed base classes is real. But a succinct base class can be very valuable and useful, and not that brittle. Just don't stuff cruft in it that is of questionable value. Ask yourself what's the least you can put in the base class and still provide value.
And this is where interfaces are also useful. You can get the isa relationship w/o much of the brittleness as there is no internal state associated with the interface. But you are still creating a hierarchy (just not of classes, but of interfaces).
It's a useful article, especially for those new to the idea. But the takeaway should be to use care. Not to avoid at all costs.
- tomphoolery 13y ago> But the takeaway should be to use care. Not to avoid at all costs. I think the takeaway here is to not try to use JavaScript as if it was some other language that has support for classical inheritance, but rather to embrace the prototypal inheritance model and compose your apps in a different way. It's not a "GOTOs considered harmful"-style rage post, but rather a warning to budding JS developers who are coming from a more classical perspective. It's not that you "shouldn't use classes", it's that you shouldn't build complex hierarchies and type systems. Keep it simple!
- ams6110 13y agohttp://javascript.crockford.com/prototypal.html http://javascript.crockford.com/prototypal.html
- pdonis 13y agoYou can get the isa relationship w/o much of the brittleness as there is no internal state associated with the interface. You can even get the relationship without brittleness but with some internal state, as long as the superclass wraps the internal state in a property. For example, in Python, the currentBalance private state would obviously be implemented as a property, not an instance variable, so that it could be mutated by subclasses while still hiding the private implementation in the superclass. (This would be harder to do in JS, I admit, since JS doesn't have anything corresponding to Python's properties.) So the lesson here isn't really "don't use class hierarchies", it's "don't use class hierarchies stupidly".
- wwweston 13y agoWith some things/people/cultures, it's not enough to say "carefully evaluate your use case and then make a decision based on the pro-con balance" -- even though that's frequently the place you want people to arrive at -- because practice is so far out of balance. In the main it seems that classical OOP with problem domains modelled in inheritance heirarchies is what's been taught as the standard to aspire to for the last two decades. The fragile base class problem and other criticisms aren't unknown, of course, but awareness doesn't seem to have dispersed as widely as the practice of lots of subclassing, which is usually introduced as an essential OOP component in the first few lessons. It might be too much to say "don't use inheritance, ever." But it might not be too much to paraphrase Knuth about optimization and give people two rules regarding it: (1) don't use it (2) (for experts only) don't use it yet.
- neilk 13y ago[edited because apparently I can't read; kenjackson did mention interfaces] I think it's still a bad idea - as you note, isa is available without necessarily having inheritance; we know inheritance is dangerous, so why include that? In languages like C++, C# and Java, it has long been expert advice to avoid inheritance where possible, and use interfaces. But the language and language culture is leading everyone astray. Defining interfaces is usually harder or stranger-looking, and is taught as an adjunct to inheritance. Other languages get this more right. Haskell has what it calls typeclasses, but they are more similar to interfaces in the aforementioned languages. We seem to be making exactly the same mistake in the ECMAScript standard, except it's even worse; you can't define an interface even if you wanted to.
- jkrems 13y agoWhat would "defining an interface" even mean in a non-type checked language? I'd say: ECMAScript already has better interface support than Java has because it supports implicit interfaces. In Java two classes can only be interface-compatible if they have a shared dependency/are at least indirectly coupled. In a language with duck typing and without static typing interfaces are present implicitly.
- neilk 13y agoYou're correct that adding interfaces to JavaScript would also require adding optional type declarations. But there are lots of languages based on JavaScript, or which compile to JavaScript, which offer optional type declarations. It seems to me they could have gone down this path. I don't agree that it's better to have an "interface" which exists purely in the head of every programmer working on the code. Languages can be doing more for us, and it doesn't have to be the kind of verbosity that Java offers.
- jkrems 13y agoMaybe that was a misunderstanding: I didn't mean to say that interfaces should exist purely in the head of the programmer. I did say that implicit interfaces/protocols (Go, Objective-C) are better than interfaces that need shared dependencies (Java/pure virtuals in C++). If I had to order it I'd say: duck typing better than explicit interfaces; implicit interfaces that are backed by static type checks "better than" duck typing. The "better than" in quotes for the latter because it really is more about how much static analysis the language supports and it's more a matter of opinion. But I'm relatively convinced that interfaces/protocols that require coupling of implementations are clearly inferior to the ones that are implicit.
- tel 13y agoI think the takeaway is often that inheritance doesn't give you isa relationships; it gives you one tool for building isa relationships. So long as you use it judiciously and ensure that you're creating a genuine supertype then things are OK.