logoalt Hacker News

Rust is beyond object-oriented, part 3: Inheritance (2023)

32 pointsby zahrevskylast Saturday at 2:15 PM38 commentsview on HN

Comments

xliiyesterday at 8:20 AM

After my adventures with different languages I'm on the hill that Rust traits, Haskells typeclasses, (sic!) Go's interfaces, etc. are state-of-art features in modern programming languages.

It's not like they're without the footguns - they have plenty. But even with those footguns typeclasses (as I'd rather call them) are complexity escape hatches.

E.g. at some point your type can have dozen of different implementations and you can decide to ignore that fact completely while proceeding to work on your (very narrow) piece of pie ignoring vastness of universe[^0] you found yourself in.

That being said multiple inheritance fits the same category and with minimal squinting same features can be found in languages such as Clojure or Elixir.

As other commenters mentione this is not a secret by any means, as composition over inheritance advice is decades old, but IMO still worth repeating because there might be someone who doesn't know it yet :)

[^0]: By universe I mean code implementional universe, not The Universe

show 3 replies
misja111yesterday at 7:55 AM

I see the author fighting really hard against a paradigm that was already well known to be suboptimal 20 years ago .. "Favor composition over inheritance" is a phrase that became common knowledge in e.g. the Java world half way during the 2000's.

It was even already mentioned in the famous Design Patterns book from the GOF in 1994.

show 1 reply
barrenkoyesterday at 10:14 AM

If I squint a little, this is similar to https://fsharpforfunandprofit.com/.

zozbot234yesterday at 8:13 AM

It's worth noting that you can replicate implementation inheritance pretty much as-is in Rust by using the generic typestate pattern. This is effectively what OP calls "policies" except that the policies can also bundle data of their own, just like our derived classes of old; they aren't just limited to picking some statically-known behavior at compile time.

The key difference compared to OOP inheritance is simply that generic typestate is explicitly anti-modular: your "base" and "derived" slices are expressly contained within a single program module. You still have extensibility - you can create new "derived" slices to go with some existing "base" - but now there is no attempt to use implementation inheritance as a "programming in the large" strategy or pattern; that is done by using more robust modularity mechanisms.

azangruyesterday at 8:12 AM

Pardon my ignorance, both about the history of computing and about Rust, but weren't the "new" keyword, and the term "instance" introduced in object-oriented languages? If yes, isn't it deceptive then that Rust has the "new" method, and that the Rust book describes it as creating an instance?

show 1 reply
jqpabc123last Saturday at 2:29 PM

Inheritance may have some limited utility but it often degenerates into "spaghetti code" dressed up to appear modern and acceptable.

Just like "goto" in the days of old, it is best used sparingly.

show 4 replies