Atlas · Details
When Polymorphism Fails
AI Notes
Steve picks a fight with the orthodoxy. The textbook line — if you
reach for instanceof you are doing OO wrong — is true
most of the time, and he says so up front. His piece is about the
exception, demonstrated by the OpinionatedElf: a user-contributed
extensible-system creature whose entire purpose is to announce which
other monsters it hates. The polymorphic move is obviously absurd
(add a doesMrOpinionatedElfHateYou() method to all 150
monsters), and even Ruby's open-classes trick — which can patch the
method onto each monster from inside the elf's own file — fails the
moment a new monster appears that the elf has never seen. The thesis:
polymorphism only makes sense when the polymorphic behavior is
really a behavior of the target; when it's the behavior of the
observer, you need runtime typing. The security-guard analogy
seals it — you don't ask each person entering the building to
implement their own doYouHaveAccess() method; the guard
does the check.
Steve also flags in a footnote (and follows through on for years afterward) that type is better represented by properties than by classes. The piece pairs with Execution in the Kingdom of Nouns as the design-essay foundation of Steve's long-running argument with class-based OO orthodoxy — Polymorphism Fails is the technical case, Kingdom of Nouns the same case as comedy. The "Opinionated Elf" makes appearances in the archive for years afterward as Steve's recurring stand-in for the bad-OO-fit case.
Related listings
-
2008
The Universal Design Pattern
The constructive companion to this piece. Where Polymorphism Fails catalogues the cases the classical OO type system can't handle, the Universal Design Pattern offers the property-map approach Steve reaches for when inheritance gives out.
-
2006
Execution in the Kingdom of Nouns
Two years later — the funnier, more famous companion. Polymorphism Fails is the technical core of Steve's beef with Java-style OO; Kingdom of Nouns is the same beef as comedy.
-
2005
Choosing Languages
Same arc — the framework piece. Polymorphism Fails is one of the design lessons that shaped which languages Steve was steering toward in the column.
From the peanut gallery
Read the rest of the thread · 1 more
-
> polymorphism only makes sense when the polymorphic behavior
> is really a behavior of the target. When it's the behavior
> of the observer, you need runtime typing.
Is it runtime type-checking that is called for, or does it just look like that because Java overloads "instanceof" to test for type — and interface?
In Objective C, for example, you could use protocols (i.e. "interfaces") to implement the marker interface pattern. Objc Categories (a way of packaging extensions to a pre-existing class) would enable you to pretty cleanly extend the relevant monster classes from the comfort of the Elf interface file. You could then test it like so...
if ([creature conformsToProtocol: @protocol(AnnoysElves)]) { ... }Perhaps this approach would avoid inadvertently conforming to
@protocol(AnnoysMartinFowler).
Yeah, using Objective C protocols and marker interfaces is similar to Ruby's approach (Ruby stole the best stuff from -every- language...). In Ruby you can modify any class; they're always "open", and Ruby's been switching to something they call "duck typing", which is exactly the difference between conformsToProtocol() and instanceof. They call it respond_to?, but it's the same basic idea: they don't care what the overall type of an object is, just whether it responds to a message with the right signature. There's always the chance that it can be mistaken identity, but with reasonably specific method names you can avoid that pretty well.
I'm not sure if it would appease Fowler and friends, though, since it's either violating encapsulation (by mucking with classes at runtime), or polymorphism (by not mucking with them). I don't think they've addressed this situation in the books; maybe we should just ask him about it. :)
— Steve Yegge · September 22, 2004 05:06 AM