Live data from Hacker News

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

lists.canonical.org

41–50 of 134 posts

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

#41
>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.size2/2 * (1 - (1 - age2)*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.

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?

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

#42
post #7

Heh, I agree somewhat that the Duck>Animal is a bit annoying.. but this: 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…

Probably if you have a trivial piece of code, you don't need inheritance to help you structure it. But you're right that we need a smaller example than the entire class hierarchy of Pygmusic. What do you think would be the smallest sensible example?

If your objective is only to explain what inheritance is rather than why someone would use it, you could probably write two classes and three methods:

    class A:
        def z(self):
            print "z " + self.y()
        def y(self):
            return "Ay"

    class B(A):
        def y(self):
            return "By"

    A().x()
    B().x()
But I really think that most people will find a program easier to understand if it's not completely abstract like that — if it reflects some kind of intentional process where a programmer was trying to achieve something. But in order to explain inheritance in such a context, you need a program where inheritance makes things better instead of worse. What do you think is the simplest possible piece of code that would do that? I am thinking of a very-much-cut-down version of Pygmusic with only two drawable objects.

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

#43
post #38

Earlier quoted context omitted.

Yes, you're right, it's only a great lesson if it's taught properly. I mean, really? Doesn't that seem like hair-splitting to you? In my opinion, dickering about this is the equivalent of, "Yeah, those two hortizontal parallel lines are a great symbol for equality as far as it goes, but really students need to understand the difference between equivalence and implication!" It's an equals sign. Same deal here. It's an…

I think the point is more that the analogy is so misleading, that it hurts the student's understanding. A similar bad example would be using familiar round objects to teach equivalence: there are 10 apples, and 10 oranges, so apples == oranges. Car's don't extend vehicles, and duck's don't extend birds. Just because we can organize these physical things into conceptual hierarchies based on their functionality, doesn'…

There is a direct mapping between our natural construction of ontologies (we are pattern-detecting creatures, we naturally see commonalities across the birds) and why object orientation works. Cars are a subset of vehicles in most peoples' minds; and Buttons are a subset of Controls in most UI programmers' minds. And the topologies of these ontologies are similar enough, by design, that you can indeed teach valuable lessons using vehicles and birds.

As to polymorphism, that comes for free from understanding language. Most people will understand a "No vehicles allowed" sign to prohibit cars but not people. What else is that but an understanding of polymorphism in evaluating a predicate?

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

#44

> You can’t add code to ducks. You do if you are creating a piece of software to track ducks. 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 propo…

True, but I still don't think this is a good analogy. When you are learning inheritance you don't know what "x extends y" even means. Using a non-code example obscures what you are talking about. I'd use an example like this: HPDriver extends PrinterDriver. CanonDriver extends PrinterDriver. EpsonDriver extends PrinterDriver. See, you can make 3 different drivers and share common printer code. That makes sense to me…

I'd object to your example: your example seems to me to be closer to that of instance :: class than subclass :: superclass. PrinterDriver defines a contract; each of HPDriver, CanonDriver etc. will need to fulfill the contract. But I don't see them usefully adding behaviour. The OS would have to already know about HPDriver in order to use its extra functionality - then what's the point in using inheritance at all?

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

#45
post #38

Earlier quoted context omitted.

Yes, you're right, it's only a great lesson if it's taught properly. I mean, really? Doesn't that seem like hair-splitting to you? In my opinion, dickering about this is the equivalent of, "Yeah, those two hortizontal parallel lines are a great symbol for equality as far as it goes, but really students need to understand the difference between equivalence and implication!" It's an equals sign. Same deal here. It's an…

I think the point is more that the analogy is so misleading, that it hurts the student's understanding. A similar bad example would be using familiar round objects to teach equivalence: there are 10 apples, and 10 oranges, so apples == oranges. Car's don't extend vehicles, and duck's don't extend birds. Just because we can organize these physical things into conceptual hierarchies based on their functionality, doesn'…

No, it's not misleading. It is insufficient to capture the totality of what is meant by object-oriented programming and polymorphism. But it is not misleading. It is simply a very narrowly applicable -- but very useful, when leveraged properly -- analogy.

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

#46
post #6

Earlier quoted context omitted.

You can explain is-a using examples that actually make sense to model using inheritance, like a set of game objects that have an interface like: class GameObject { public: // Called every frame to update the object's logical state. void Update(GameState* state); // Called to draw the object. Draw(GraphicsContext* context); } class EnemySpaceship : public GameObject { /* ... */ }; class SpaceDebris : public GameObject…

>rather than to make it a pointless ontological exercise of whether a Square is-a Rectangle or vice-versa it isn't pointless. It is the key point of the design : http://www.objectmentor.com/resources/articles/lsp.pdf

It is pointless if you make it an ontological exercise. If you make it a question of substitutability (as your link does), then I agree that you're doing it the right way.

The question shouldn't be: "is a Square a special kind of Rectangle, in a pure/platonic/logical sense?" The question should be "can a Square be treated as if it were a Rectangle." The answer to the second question could depend on the program and what it wants to do! The first is a rathole that accomplishes nothing.

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

#47
post #44

Earlier quoted context omitted.

True, but I still don't think this is a good analogy. When you are learning inheritance you don't know what "x extends y" even means. Using a non-code example obscures what you are talking about. I'd use an example like this: HPDriver extends PrinterDriver. CanonDriver extends PrinterDriver. EpsonDriver extends PrinterDriver. See, you can make 3 different drivers and share common printer code. That makes sense to me…

I'd object to your example: your example seems to me to be closer to that of instance :: class than subclass :: superclass. PrinterDriver defines a contract; each of HPDriver, CanonDriver etc. will need to fulfill the contract. But I don't see them usefully adding behaviour. The OS would have to already know about HPDriver in order to use its extra functionality - then what's the point in using inheritance at all?

In a lot of OO languages instances rarely have different behaviour to each other.

You are also forgetting that it's possible to have more than one printer using the same driver (i.e. multiple instances of a class of printers). This is not uncommon when you consider network printers.

> The OS would have to already know about HPDriver in order to use its extra functionality

And that isn't true of any other instance in which inheritance is used?

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

#48
post #10

Earlier quoted context omitted.

Most of the benefits of OO programming come from abstracting the machine / concerns (eg. MVC) rather than modeling the domain. (eg. Cars / Ducks / etc). I know it's just an example but it raises several important questions: Why does the GameObject need to know how to render itself? Why does the GameObject update the GameState which the GameObject is ostensibly also a part of? Does updating the GameState directly affe…

Code savings isn't a reasonable goal of OOP. Information-hiding (in which you take an arbitrarily-complicated method and abstract it behind a class) is.

When you give people inheritance all they see is hierarchies and when you give them information hiding systems all they see is access control.

One should not be able to find trade secrets by grepping for "private", nor reproduce a companies org chart by a class inheritance graph.

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

#49
post #9
post #6

Earlier quoted context omitted.

You can explain is-a using examples that actually make sense to model using inheritance, like a set of game objects that have an interface like: class GameObject { public: // Called every frame to update the object's logical state. void Update(GameState* state); // Called to draw the object. Draw(GraphicsContext* context); } class EnemySpaceship : public GameObject { /* ... */ }; class SpaceDebris : public GameObject…

Is "Spaceship extends GameObject" really that different than "Duck extends Animal"?

Yes, because drawing a bunch of game objects on a screen is something a real program might actually want to do, and therefore opens up opportunities to talk about real-world design tradeoffs.

Making a program print "quack" when you call the "speak()" method is something that only happens in textbooks, and since there's no reason to actually do that there's no easy way to discuss the alternatives and why polymorphism is a win.

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

#50
post #44

Earlier quoted context omitted.

True, but I still don't think this is a good analogy. When you are learning inheritance you don't know what "x extends y" even means. Using a non-code example obscures what you are talking about. I'd use an example like this: HPDriver extends PrinterDriver. CanonDriver extends PrinterDriver. EpsonDriver extends PrinterDriver. See, you can make 3 different drivers and share common printer code. That makes sense to me…

I'd object to your example: your example seems to me to be closer to that of instance :: class than subclass :: superclass. PrinterDriver defines a contract; each of HPDriver, CanonDriver etc. will need to fulfill the contract. But I don't see them usefully adding behaviour. The OS would have to already know about HPDriver in order to use its extra functionality - then what's the point in using inheritance at all?

A common pattern is a superclass with "abstract" methods that subclasses then implement. So the `sendCommand(cmd)` function is implemented in HPDriver and CanonDriver and higher level methods in PrinterDriver can use that piece even though PrinterDriver itself has no implementation of that method.
Post reply on HN