The object-oriented part of OCaml, by the way, has inheritance that's entirely orthogonal to interfaces, which in OCaml are static types. Languages like Smalltalk and, for the most part, Python don't have interfaces at all.
The object-oriented part of OCaml, by the way, has inheritance that's entirely orthogonal to interfaces, which in OCaml are static types. Languages like Smalltalk and, for the most part, Python don't have interfaces at all.
Someone has already referenced "Adding Dynamic Interfaces to Smalltalk" [0] and looking back there doesn't seem to be any kind of demonstration that use of interfaces makes software faster to develop or less error prone or... [1]
[0] https://www.jot.fm/issues/issue_2002_05/article1/
[1] https://www.cs.utexas.edu/~wcook/papers/OOPSLA89/interfaces.pdf "We are not finders of fact. We are tellers of story.
You base the story on the evidence, no?
No! We base the evidence on the story. We prove what helps us, and we disprove what hurts us. Whoever tells the best story goes home with the cash-in prizes."
(The Good Fight, season 3 episode 2. 30 - 31 minutes. CBS All Access 2019.)"Trait/Typeclass"-style compositional inheritance as in Rust and Haskell is sublime. It's similar to Java interfaces in terms of flexibility, and it doesn't enforce hierarchical rules [1]. You can bolt behaviors and their types onto structures at will. This is how OO should be.
I put together a visual argument on another thread on HN a few weeks ago:
https://imgur.com/a/class-inheritance-vs-traits-oop-isnt-bad...
[1] Though if you want rules on bounds and associated types, you can have them.
Yes-and-no.
Interfaces still participate in inheritance hierarchies (`interface Bar extends Foo`), and that's in a way that prohibits removing/subtracting type members (so interfaces are not in any way a substitute for mixins). Composition (of interfaces) can be used instead of `extends`, but then you lose guarantees of reference-identity - oh, and only reference-types can implement interfaces which makes interfaces impractical for scalars and unusable in a zero-heap-alloc program.
Interface-types can only expose virtual members: no public fields - which seems silly to me because a vtable-like mechanism could be used to allow raw pointer access to fields via interfaces, but I digress: so many of these limitations (or unneeded functionality) are consequences of the JVM/CLR's design decisions which won't change in my lifetime.
Rust-style traits are an overall improvement, yes - but (as far as my limited Rust experience tells me) there's no succinct way to tell the compiler to delegate the implementation of a trait to some composed type: I found myself needing to write an unexpectedly large amount of forwarding methods by hand (so I hope that Rust is better than this and that I was just doing Rust the-completely-wrong-way).
Also, oblig: https://boxbase.org/entries/2020/aug/3/case-against-oop/
"Only reference types can implement interfaces" is simply not true in C#. Not only can structs implement them, but they can also be used through the interface without boxing (via generics).
(If you merge multiple interfaces, the implementations of the methods have to match. You end up with even more special getters for each one sometimes.)
It's true that you can't access private members (not just fields) on `this` from the mixin interface. But explicit implementations of members mean that only someone explicitly downcasting the object will get access to those members, so accidental access is not an issue.
Those default-implementations are only accessible when the object is accessed via that interface; i.e. they aren't accessible as members on the object itself. Furthermore, interfaces (still) only declare (and optionally define) vtable members (i.e. only methods, properties, and events - which are all fundamentally just methods), not fields or any kind of non-static state, whereas IMO mixins should have no limitations and should behave the same as though you copied-and-pasted raw code.
That's true in C# but not in Java, so it's not something intrinsic to the notion of an interface.
> Furthermore, interfaces (still) only declare (and optionally define) vtable members (i.e. only methods, properties, and events - which are all fundamentally just methods), not fields or any kind of non-static state
This is true, but IMO largely irrelevant because get/set accessors are a "good enough" substitute for a field. That there is even a distinction between fields and properties in the first place is a language-specific thing; it doesn't exist in e.g. Eiffel.
int Foo { get; set; }