logoalt Hacker News

saidinesh501/22/20253 repliesview on HN

Never using inheritance is pushing the dogma to the other extreme imo. The whole prefer composition over inheritance is meant to help people avoid the typical OO over use of inheritance. It doesn't mean Is-A relation doesn't/shouldn't exist. It just means when there is data, prefer using composition to give access to that data.

There will be times when you want to represent Is-A relationship - especially when you want to guarantee a specific interface/set of functions your object will have - irrespective of the under the hood details.

  Notifier n = GetNotifier(backend_name);
Here what you care about is notifier providing a set of functions (sendNotification, updateNotification, removeNotification) - irrespective of what the implementation details are - whether you're using desktop notifications or SMS notifications.

Replies

bedobi01/22/2025

I see no need for inheritance there, that can and should be done using interfaces

eg in the contrived example I gave, any of all three of the User, Student and Employee can implement the interface (and if needed Student could simply delegate to its internal User while Employee could "override" by providing its own, different implementation)

show 1 reply
cryptonector01/22/2025

If you have a sufficiently statically typed language then the is-a concern goes away -- certainly in the example you gave, since the compiler/linker knows to look for a `GetNotifier()` that returns a `Notifier`. Now, you might still want to know whether the notifier you got satisfies other traits than just those of `Notifier`, but you do that by using a type that has those traits rather than `Notifier`, and now you have little need for `instanceof` or similar operators. (You still might want to know what kind of thing you got because you might care about semantics that are not expressed in the interface. For example you might care to know whether a logger is "fast" as in local or "slow" as in remote, as that might cause you to log less verbosely to avoid drops or blocking or whatever. But the need for this `instanceof` goes down dramatically if you have interfaces and traits.)

foobarkey01/22/2025

Never is a good starting point as a guide but of course there are cases where is-a makes sense too.

Composition generally is not good enough to model all cases without resulting to some AOP or meta programming also, but in that case the is-a or a base class would arguably be the simpler approach, at least it can be reasoned about and debugged, as opposed to some AOP/Meta spaghetti that can only probably be understood from docs