Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

My experience is almost the exact opposite of yours! The first problem is that the expression "is-a" is notoriously vague. If class A has method a, and class B subclasses a, can B override method a? In what sense is B an A if it does not obey Strict Liskov Substitutability?

The second problem is that re-use is an easy problem to solve in any language. We have delegation, we have proxies, we have so many tools. Why use inheritance, which mixes two different concepts (is-a and was-a a/k/a is-implemented-using)?

Lastly, how is the code more conducive to later changes? In my experience, you now have a problem where changing class A changes the behaviour of every class that extends A. This is a notoriously tricky problem in the real world. In theory, that change ought to change every subclass and inheritance is a win. In practice, the people writing all those subclasses did so making assumptions about the behaviour of A at the time it was written, much as there are billions of lines of windows code that depend on its bugs and break the moment you fix a bug.

Encapsulation is a wonderful thing. I do not see implementation inheritance as having anything whatsoever to do with encapsulation. If anything, I see the opposite.

If I write that B is-a A, if these things are fully encapsulated, shouldn't it be a black box as to how B manages to behave exactly like an A? Maybe there's some shared code, but then again, shouldn't it be possible for B to use some other completely different implementation? That's encapsulation to me. Forcing interface inheritance to be twinned with implementation inheritance breaks encapsulation in my opinion.



I completely agree with your point. The way inheritance is always taught is through the "is-a" rule of thumb and I think that's so detrimental to the students that they'd be better off if they didn't know inheritance existed. The phrase "X is-a Y" often appears to make sense because of the real world (e.g. "Cat is-an Animal"), but it makes people forget that it may not make sense in the world they are trying to model. It may be that the relationship between a Cat object and an Animal object is completely different in your system than in the real world. If it is, then you run into the problems with future changes you already mentioned.

I also second your point on code reuse. Code reuse/removal of duplication is the main reason behind all programming languages and paradigms. Inheritance is a tool provided by OOP languages. Therefore, to say that it enables code reuse is basically trivial.


I have discovered a truly marvellous follow-up to your comment, which this box is too small to contain.

http://github.com/raganwald/homoiconic/blob/master/2010/12/o...


Yes, absolutely. Thinking about design in terms of defining an ontology is a great insight. Every object has a name and is therefore a part of some sort of semantics. However, what it does (it's meaning) is up to the designer. Therefore, words are naturally overloaded - they represent what we they do in reality, and their analog in our system.

As an example, let's assume we're developing a game where cats battle all sorts of other animals for survival. Certainly, the designer has good reason to call the object representing the protagonists in the game Cat. The programmer also has good reasons to call the enemies of the cat Animals, since they will all do the same thing (e.g. attack the cat). However, in this case a Cat is definitely not an Animal. Cat is an overloaded word - it no longer means "feline". Similarly, Animal means something completely different - it's more akin to "enemy". If we could substitute the "natural" ontology of these words with the one our objects define, we would be able to tell that the statement "A Cat is an Animal" is senseless.

I think OOP actually tries to take advantage of the "natural" ontologies we have constructed through experience. This is why this is such a subtle design issue. I'm not quite ready to say it "gets it backwards", but it certainly doesn't mirror the way we naturally look at the world.

I hope I'm mirroring and expanding on what's been said here. I'd love to read your thoughts.


Just FYI, you can resize the box. Drag the little icon in the bottom right-hand corner.


You ask good questions. The right solution depends on the problem; it's difficult for me to disagree with your conclusions when I don't know the problem domain or framework around which your examples exist. Maybe we work on fundamentally different kinds of problems, or right code with fundamentally different structures, and thus where inheritance frequently works amazingly well for me, it fits poorly for you.

Good design is hard.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: