TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Goodbye, shitty "Car extends Vehicle" object-orientation tutorial

232 pointsby sebkomianosalmost 14 years ago

32 comments

d0malmost 14 years ago
Heh, I agree somewhat that the Duck&#62;Animal is a bit annoying.. but this:<p><pre><code> Here’s an example that I think would be better to use instead: the `Visible` hierarchy in [Pygmusic][], which is a kind of software drum machine. A `Timer` is a horizontal strip on the screen with a stripe racing across it. A `NumericHalo` is a spreading ripple on the screen that fades. A `Sound` is a thing on the screen that makes a sound when a `Timer`’s stripe hits it. A `Trash` is a thing that deletes `Sound`s when you drop them on it. They all inherit from `Visible`, which represents things that can be drawn on the screen and perhaps respond to mouse clicks or drop events, but they do different things in those three cases. In addition, the `Trash` and `Sound`s are subclasses of `ImageDisplay`, because the way they handle being drawn is simply to display a static image, so that code is factored into a superclass. </code></pre> Is by far worst.. The goal of the Person or Duck is to pick a <i>trivial</i> example to explain some concept. Of course you're not building Sim city and that it will be totally different in real apps.<p>Also, it's true that inheritance is often the wrong solution and could arguably be said that it create more problems than it solves. However, before understanding all the pitfalls and the why/why not of inheritance, you first need to <i>understand</i> what inheritance is!<p>So, instead of <i>shooting</i> someone who give an example with a Duck to explain OO, let just say that this tutor should say beforehand "Let's take a trivial example to understand the concepts of OO. Later on, we'll see why this is not always the preferred solution."
评论 #2916444 未加载
评论 #2914867 未加载
jeffreymcmanusalmost 14 years ago
&#62; You can’t add code to ducks.<p>You do if you are creating a piece of software to track ducks.<p>I don't get the impression that the person who wrote this ever had to seriously teach software development to software developers. Simplistic metaphors are used so frequently for this kind of thing because it prevents the learner from having to ascend more than one conceptual hurdle at a time. The alternative that he's proposing (learning inheritance in terms of some obscure drum machine software) would imply that the learner spend half their time digesting how this drum machine works, then the rest of their time (assuming they're still awake) figuring out how that relates to inheritance. It isn't helpful.
评论 #2914782 未加载
评论 #2914556 未加载
评论 #2914552 未加载
评论 #2914725 未加载
评论 #2914750 未加载
评论 #2914529 未加载
SingleShotalmost 14 years ago
I disagree with the arguments in general and find that modeling real world, common items is much more illuminating from a teaching/learning point of view. It would be an ridiculously long post to explain why, but here is an example picking one of the author's bullet points: "Penguins don’t implement the fly method that can be found in birds."<p>Should bird even have a fly method? Only if all birds fly. And the application will have penguins, so the answer is "no". This doesn't make the Duck extends Bird example a bad thing though. It points out that if you do shallow domain analysis, you will end up with a poor OO design where you shoehorn things like "fly" into penguins for example.<p>If some birds fly and some don't, some swim and some don't, some burrow and some don't, etc. you might implement this with "mix in" interfaces like "Flyer", "Swimmer", "Burrower", etc. This is a good lesson in how one can distribute different behaviors across a class hierarchy without polluting the common base interface of the hierarchy (i.e. without forcing all birds to fly). However, this burns the behavior into the concrete classes, prevents things like modeling the fact that baby (or dead) birds cannot fly/swim/burrow, and does not allow for sharing different fly/swim/burrow implementations across bird implementations (in languages like Java anyway). In other words, it shows why inheritance can be a good choice, and also a bad choice.<p>A common solution to this would be to use two hierarchies - one is the bird hierarchy that all birds implement (with behaviors like "preen feathers"). The other is the behavior hierarchy that all behaviors implement. Birds "contain" a list of behaviors. Code that operates on birds knows the bird interface has methods that make sense for all birds. Code that operates on behaviors like fly/swim/burrow would have behaviors passed in, or perhaps ask the animal in question "do you know how to fly?" and if yes, ask for its fly behavior. There are many variations on this, but the point is that there is a separation of concerns: bird concerns and behavior concerns. This helps teach the trade-off between inheritance and containment (e.g. behaviors not burned in through inheritance can be added/removed over time, for example, when a baby bird learns to fly).<p>The point though is that this kind of example (Duck extends Bird) helps one understand how to model real world items so they match the domain, to learn about separation of concerns, learn the pros/cons of inheritance/containment, design patterns, and perhaps most importantly, do so using concepts most people will more readily understand (cars or birds or people).
评论 #2914842 未加载
thaumaturgyalmost 14 years ago
Way back when I was first learning OOP, the typical "car extends vehicle" examples caused me not to see the practical point of OOP for a long time. I <i>still</i> resist using object-oriented approaches except in cases where the code demands it. (A feature, not a bug?) And, these days, if I do use OOP in places in the code, it's for encapsulation -- which is only a <i>style</i> consideration -- so the "car extends vehicle" example still doesn't apply.<p>I think a simple example from GUI programming would do much better. How about window classes? I did something like this recently:<p><pre><code> class Window { public method show() public method title(newTitle) public method close() } </code></pre> Easy enough. What if I want a modal window though? Almost everything in it would be the same as a regular window, except I might need to do some things slightly different for show()ing and close()ing the window. Aha! A perfect example of an appropriate time to create a subclass:<p><pre><code> public class ModalWindow extends Window { public method show() public method close() } </code></pre> Programming tends to attract practical individuals. I think teaching "car extends vehicle" then is usually going to cause one of two results: either a student that then uses that approach all the time, even in cases where it's not warranted, because they don't understand when it's appropriate and when it's not; or a pragmatic student that resists using it because the given examples don't apply to anything that they're actually going to have any chance of working on.
评论 #2915036 未加载
评论 #2914791 未加载
评论 #2914799 未加载
mcphilipalmost 14 years ago
The only situation where I could see not wanting to hear the car extends vehicle example of inheritance is in an interview where you want the candidate to give a practical example of inheritance. I see nothing wrong with using an example even a child could understand as a first stab at explaining inheritance.<p>Fairly annoying how quickly a mostly useless rant such as this has jumped to the top of HN.
dustingetzalmost 14 years ago
He asks for a simpler example. How about a collections api? Start with array, then linked lists, then functioms like contains and filter and which need an iterable interface, then different types of linked list, then add hashmap where you iterate keys, then different types of map e.g. linked map. This is all data structures 101 material anyway! After this primer, a simple GUI toolkit isn't as far out of reach.
MarkMcalmost 14 years ago
I think the best introduction to object oriented design is shown in the first chapter of Martin Fowler's book "Refactoring"<i>. He gives the example of a DVD rental shop that has to calculate the rental fee based on the type of DVD: - A New Release is $3 per day - A Children's DVD is $1.50 for three days, then $1.50 per day after that - A Standard DVD is $2 for two days, then $1.50 per day after that<p></i> <a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672" rel="nofollow">http://www.amazon.com/Refactoring-Improving-Design-Existing-...</a>
评论 #2916207 未加载
perlgeekalmost 14 years ago
I've been working on writing a programming book for quite some time now, and I can tell you that coming up with good examples is really hard.<p>For me, a good example meets as many as possible of the following demands (in no particular order).<p>An example should<p>* demonstrate the feature or concept under discussion<p>* be short - shouldn't be more than half a page to a page<p>* solve a problem that the reader can easily understand<p>* solve an interesting problem<p>* not use unrelated features of the language or library that haven't been introduced yet<p>* should avoid complexity unrelated to the feature or concept under discussion<p>* should be as close as possible to what one would use in "serious" (ie non-teaching) programming<p>I found that i spent about as much time searching for good examples as actually writing text or code for the book. I'm pretty happy with some of the examples (for example the chapter on grammars parses JSON, which is rather real-world, but not too complicated), some of them still fail most of the demands given above.<p>(If you're curious, grab the latest PDF from <a href="https://github.com/perl6/book/downloads" rel="nofollow">https://github.com/perl6/book/downloads</a> -- it's still very much a work in progress).
5hoomalmost 14 years ago
One of the first examples of OOP I encountered was the old 'shape' hierarchy demonstration: 'shape' is a base class. 'rectangle' is a new class that inherits from shape. 'square' inherits from 'rectangle', etc.<p>It demonstrates the ".. is a .." relationship that inheritance describes perfectly.<p>This is a pretty common way to introduce OOP as it draws on stuff we all know intuitively. The example proposed with a bunch of drum machines concepts, trash, timers &#38; stripes or whatever is so mind bogglingly obscure for most people that I'm sure they would have checked out long before the actual OOP lesson begins.<p>Not sure what the point is.<p>Oh, and btw, just because you might not ever need to represent a 'duck' object, doesn't mean that it is a stupid example. Say I write a game with a bunch of actors, I might have a base actor class, a bird class that extends that, and a duck class that extends that. Bam, legitimate use for a 'duck' object. There's probably a lot more people wanting to write "a clone of the sims" than "an intractably obscure drum-machine".
评论 #2915472 未加载
评论 #2915791 未加载
silverlakealmost 14 years ago
Depends on the audience. If you're using the "Car : Vehicle" example, you're probably explaining the basics of OO to a newbie. I think that's a fine example. If you're talking about more advanced topics, then you can use a more advanced example. In fact, you can use different examples suited to different topics! Relax, there's no need to be a pedant.
评论 #2914746 未加载
CodeMagealmost 14 years ago
The problem people have with "Car extends Vehicle" is that they expect magic. It's the same impatience we sometimes feel with little kids because they're not grasping something we've been taking for granted for decades. If you're trying to teach someone <i>new</i> to OOP, there is <i>no</i> example that will take them from their current level of knowledge to yours, in one fell swoop. You can't expect them to grapple with decisions such as "inheritance vs. delegation" when they're only now learning what inheritance is all about.<p>So yeah, "Car extends Vehicle" and "Duck extends Bird" works pretty well at that point. You can try to cram "Penguin" and "Helicopter" and "Flyer" and "Vehicle" down your students' throats in the same lesson, but I doubt that will magically make them digest it properly. And if you can't do that with easy stuff like "Duck" and "Bird", how do you expect them to swallow "NumericHalo" and "ImageDisplay"?
bendmorrisalmost 14 years ago
This is ridiculous. I'm teaching part of a course called "programming for biologists" this fall including the part about object oriented programming. Most of my students are ecology grad students. You're telling me I shouldn't use simple animal examples, when these are exactly the types of things my students are going to be modeling?
cemaalmost 14 years ago
1. I absolutely agree with the linked article. My perspective is somewhat different, however. I submit that OO hierarchy should not mimic whatever properties whatever <i>real-world objects</i> may happen to possess. Instead, when we solve a problem and have come up with a solution, the OO hierarchy should describe the solution. A different solution, or a different problem, may easily lead to a different hierarchy of (perhaps different) objects. And these would be <i>software objects</i>.<p>2. Therefore, I suggest that a "simple" example would come from a well-known software system. Such as a window system (rectangle, button, icon, window, etc) which, either as a concrete example or an abstraction, should be easily understood by anyone with a minimal (desktop) computer experience and no programming experience.
siglesiasalmost 14 years ago
I completely agree with this. Duck-laden object oriented programming tutorials made no sense as I tried to transition from C to Objective-C.<p>The best explanation I found was Chapter 2 of Apple's "Object-Oriented Programming with Objective-C":<p><i>Every object has both state (data) and behavior (operations on data). In that, they’re not much different from ordinary physical objects. It’s easy to see how a mechanical device, such as a pocket watch or a piano, embodies both state and behavior.</i><p><a href="http://developer.apple.com/library/mac/documentation/cocoa/conceptual/OOP_ObjC/OOP_ObjC.pdf" rel="nofollow">http://developer.apple.com/library/mac/documentation/cocoa/c...</a>
kenjacksonalmost 14 years ago
I actually think these are really good examples. I especially like the shape example, because you quickly run into problems where you can talk about the difference between modeling for a solution and representing an abstraction.
gueloalmost 14 years ago
I fail to see the problem. I would bet that there are tons of real games that actually have a Car class that extends Vehicle.
yasonalmost 14 years ago
The thing is that there ought to be no trivial examples of object oriented paradigms because they are never trivial.<p>If you're good you can create object oriented interrelations that work but end up having object charts which have that plastic, phoney kind of artificiality that makes little natural sense. If you're a god-like programmer you can come up with interrelations of code and data that make perfect sense but they're quite not always object oriented.<p>As for OO, the best thing I've settled with is this:<p>- Scoop up all your programming experience and first think how do you want to reuse some code or some data structures<p>- Then you go and look up appropriate paradigms and language features that <i>could</i> support your case of reuse<p>- And finally you go figure out how to best do it in a natural way in your programming language.<p>However, I often start with basic lists and dicts and only after something becomes truly obvious and a near-universal trait, I might make a class out of it if I can better reuse code that way. An archetypical example would be something like a BaseObject that supports some protocol for init, deinit, and refcounting, for example. Everything else can adhere to that protocol. Better yet, I'll make it an interface so I can decouple the implementation of the protocol from the definition of the protocol.
Emorealmost 14 years ago
Yes, a thousand times yes. I have never understood why dependency injection is not taught in OOP courses -- as described in the article, DI truly shows why OOP design is useful. Conversely, the "domain model"-approach commonly used probably gains some of its attraction due to the similarities to E/R database diagrams, but far from always lead to designs which are actually useful in practice.
Kevin_Marksalmost 14 years ago
Is Kragen making an elaborate joke about duck typing here?<p>Penguins don’t implement the “fly” method that can be found in birds. And you don’t go around causing things to fly without knowing what kind of bird they are. (Ducks themselves decide when they want to fly, and they certainly seem to know they’re ducks and not vultures.)
评论 #2915168 未加载
joe_the_useralmost 14 years ago
Just one piece in the whole <i>object orientation blows but still is the best thing we have to make complex systems understandable to simple people</i> quandary.<p>It is true that the real world object examples confuse everything that OO is really used for. It is also true that we need them to make OO approachable at all.<p>OO is essentially an ontological cluster-f<i>ck where multitudes of logical and representational levels are trampled on. The thing is, OO </i>uses* the adhoc mixture of logical confusions that is most people's description of their world. Somehow people's amazing brains muddle through speaking natural language despite it's terrible muddling of everything. Thus we can stand the confusion of not really knowing whether "class window" is a glowy thing on the screen, a location in memory or an abstract datatype.
BenoitEssiambrealmost 14 years ago
I would also add. Don't introduce a language by showing how to compute the Fibonacci sequence.<p>I never have and never will need to compute the Fibonacci sequence. Recursion is such an infrequent part of everyday programming that it doesn't really matter if a language makes it easier.
评论 #2915501 未加载
评论 #2915479 未加载
quanticlealmost 14 years ago
&#62;One disadvantage is that it has to deal with a fair amount of arithmetic; there's lots of `/ float(n)` and `* self.rect.w + 0.5` and `self.size<i></i>2/2 * (1 - (1 - age<i>2)</i>*2)` and the like, which I think reinforce a common misconception about computer programming: that you need to learn algebra and arithmetic in order to write programs, and that programs mostly deal with numbers.<p>Is this really such a disadvantage? Algebra and arithmetic are hardly advanced subjects. Isn't it fair to insist that programmers know at least middle school math before they program?
评论 #2915158 未加载
busteralmost 14 years ago
I don't get what is soo wrong about the car example, because of it i grasped the object orientation style instantly. What's easier to undderstand than this!?
JulianMorrisonalmost 14 years ago
Inheritance. Gah, why won't this bad idea die!<p>Shared calling protocol, shared data sub-structures, fixed compile-time equivalence hierarchy, all clumped together.<p>Go gets it right. Cut the linkage between composition and equivalence. Composition handles inclusion/merging of existing objects. Interfaces handle equivalence of objects. Interfaces can have hierarchies, but there's no one true hierarchy baked into the objects they describe.
bjoernbualmost 14 years ago
The example for inheritence I liked best was something like this:<p>Number (implementing trivial exponentiation through multiplication)<p>RealNumber &#38; ComplexNumber implementing their specific kind of multiplication.<p>Later on replace the exponentiation by fast exponentiation. This directly demonstrates the benefits of avoiding code duplication.The change only has to be made in one place.
pacmonalmost 14 years ago
The real truth being that not even one thinks the same way. Some people learn better with visuals versus some who prefer text.<p>Some people see no problem with Vehicle-&#62;Car or Animal-&#62;Duck or whatever other ultra basic OO example.<p>In the end what's best is whatever can make someone understand the concept.
wlievensalmost 14 years ago
In my experience, there's a process where adding accuracy (and thus usually complexity) to a domain model, implies removing existing inheritance assumptions.<p>For instance, in the trivial case an Employee is a Person, but when you go further you discover that there are all sorts of relations that need more detailed fleshing out. Is changing jobs just a call to Employee.setEmployer? That certainly feels akward. And as that process continues, you get a more complex domain model with comparatively less fixed inheritance relations.<p>The extends keyword sortof becomes an extend object, first-class among your domain and susceptible to dynamic behaviour.<p>But can you teach kids that in a first OO class?<p>EDIT: care to explain the downvote? I'm quite passionate about this subject so would love to debate it.
aufreak3almost 14 years ago
Good to remember Alan Kay's guideline here - "OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things."
dtreacyalmost 14 years ago
THAT'S WHY ITS A BEGINNER TUTORIAL. Get off your high horse.
评论 #2915994 未加载
therandomguyalmost 14 years ago
"Car extends Vehicle" is a perfectly fine example to introduce someone to OO programming. That's all.
评论 #2915039 未加载
georgieporgiealmost 14 years ago
If I understand correctly, this rant is about the use of simplistic examples in teaching OOP, correct? i.e. it's not just about using such examples when debating language features.<p>If so, then I very strongly disagree with this guy. I have painful memories of trying to come to grip with OO in high school in the early 90's. Sure, those zoological and automotive examples are almost insultingly trivial, but that's because you don't need real-world engineering complexity interfering when you're just trying to wrap your head around inheritance and extension!<p>Bird ==&#62; Duck makes sense because they're classes. As in, those are classes of animals in the real world, and there is a relationship among them. Expressing that relationship in code doesn't mean you're coding animals, it means you're modeling a real-world class hierarchy with your data definition.<p>I think that people are forgetting that OOP is actually <i>hard</i>. If you don't already have a very strong grasp on the underlying mechanics of a language (e.g. function pointers and vtables in C++), then it's going to always seem like magic.
评论 #2915226 未加载
sabatalmost 14 years ago
Nothing annoys me more than this kind of analogy. People who are trying to understand it can't figure out what a Duck really is in this scenario, and what it means that it's a subclass of Bird.<p>Use simple but realistic classes as examples.