Forgive my ignorance of Rust, but GUI toolkits are probably the strongest candidate for OOP style development, and everything I've read about Rust doesn't lend itself well to OOP.
There's really no such thing. You might be using pure functions from your perspective, but someone is handling all that backing layer data and mutable information.
There's no such thing as structured programming, at the assembly level it always just compiles down to conditional jumps. There's no such thing as a digital circuit, because real-world voltages are always analogue. Etc.
> Which is all dealing with retained, mutable data. Period.
Only if you choose to model your system that way. You can push the same paradigm all the way through: immutable events, and pure functions that transform an event and a previous (immutable) state into a new state.
So much for "not pointing out levels of abstraction". Maybe somewhere in the guts of the low-level runtime a mutable framebuffer is being used for now, sure, but I don't care about that any more than I care about whether my processor is jumping vs doing a conditional move.
Well, now that I think about it, I have seen a compiler bug in an IBM Java compiler where an if condition would never be hit, despite the code being fine and the Sun Java compiler working as expected.
I'm not entirely convinced. Libraries like React have succeeded in web development due to the complete lack of html having an extensible component model. Native applications don't have to worry about shoehorning a workable framework into stateless document renderers.
Elm and React for one... and all the other similarly inspired UI libs (even SwiftUI is kind of going there)... Plus the increased interested on fp UIs for games, entity systems, etc...
As every "flat" hierarchy this is inflexible and impossible to get right (think "ComboBox" or "MenuButton" for example).
A better approach are mixins. Separate ones for layout and behavior. This is much more flexible, and avoids code duplication or "crazy" inheritance hierarchies at the same time.
Rust Traits are ideal for mixins. So a GUI toolkit in Rust should be just fine.
That's one way to do it, but you could have something very similar that uses composition instead of inheritance (and a nice trait hierarchy to top it off). MyCustomToggleButton would contain an instance of ToggleButton and override some behavior while implementing ToggleButtonInterface or whatever. I don't know if that's the way to go but that'd work.
It pretty much is. But it's not exactly class inheritance, so most people don't consider Rust to be OOP. Structs ("classes" in Rust) can implement Traits and Traits can "inherit" each other, but structs can't inherit implementations from other structs.
> Structs ("classes" in Rust) can implement Traits and Traits can "inherit" each other, but structs can't inherit implementations from other structs.
Right, this is textbook interfaces used for composition.
Let me paste you a few paragraphs from the GoF book, released in 1994:
> Inheritance versus Composition
> The two most common techniques for reusing functionality in object-oriented systems are class inheritance and object composition. As we've explained, class inheritance lets you define the implementation of one class in terms of another's. Reuse by subclassing is often referred to as white-box reuse. The term "white-box" refers to visibility: With inheritance, the internals of parent classes are often visible to subclasses.
> Object composition is an alternative to class inheritance. Here, new functionality is obtained by assembling or composing objects to get more complex functionality. Object composition requires that the objects being composed have well-defined interfaces. This style of reuse is called black-box reuse, because no internal details of objects are visible. Objects appear only as "black boxes."
...
> Object composition has another effect on system design. Favoring object composition over class inheritance helps you keep each class encapsulated and focused on one task. Your classes and class hierarchies will remain small and will be less likely to grow into unmanageable monsters. On the other hand, a design based on object composition will have more objects (if fewer classes), and the system's behavior will depend on their interrelationships instead of being defined in one class.
Like, it's the most well-known OOP design book and it states exactly that - more than a QUARTER CENTURY ago. Who in hell argues that this isn't oop ?!
Even the bible has more than ONE single interpretation, and as much as you would like, GoF isn't the bible of OOP, just a famous book among plenty of others.
Maybe widen the bibliography of OOP programming languages beyond Smalltalk and C++ patterns?
They're not wrong, though - Rust really doesn't need implementation inheritance to be considered OO. It just needs some notion of object identity, and virtual dispatch - and it has both.
Indeed, that is why reducing OOP to implementation inheritance is a very constrained view of the paradigm.
Just like placing ECS against OOP, when they are discussed across OOP SIGPLAN papers and are the genesis of language features like Objective-C, CLOS/Flavor protocols and Smalltalk categories.
I guess, as always, the blame lies in how we teach these subjects and many don't do it properly.
Traits are just like Objective-C protocols, pretty much OOP to anyone that bothers to read about the various approaches how OOP concepts can be implemented.
There are plenty of ACM and IEEE papers if you want to see it being called OOP.
OOP is strictly run-time polymorphism. It may be that in some instances of OOP, what calls what is deducible at compile time. That subset alone is not OOP.
OOP means that an object which does not exist now can be written in the future, and loaded into code which has already been compiled and is already running now. The method calls in this existing code will correctly resolve to the method implementations in that object.
I got the impression from what I saw (coming into the scene a little too late to say from direct experience) that languages like C++ and Java, intentionally or not, did a great job of capturing how procedural programmers implemented the thick, rich, stateful GUIs that were common at the time. GUI widgets were literally the textbook example that many books used to explain classes and inheritance in a way that procedural programmers could relate to. So, I would say that the OOP style of GUI programming was a continuation of the procedural style that brought the old way of thinking to new "heights" through the new OOP language constructs.
Yes, GUIs have both been greatly benefited by the availability of OOP and a great force on the popularization of that paradigm. I think nobody will disagree that GUIs are kinda hard to create in purely structured code, and OOP makes compares much better.
But we are not at the 80's anymore, and have more options now. There is very little you can do with OOP that you can't in Rust, and a whole lot of things Rust adds to it. Just because things evolved this way it does not mean they are optimal.
Rust is great, but it can't do very basic things that OOP offer. You can't make a simple observer in Rust without RC<RefCell<T>>, unsafe, global-ish mutable state, or being forced into some framework.
You can always copy the observer into the observed structure (and avoid a lot of complications - observers are best created with FP, not OOP). You can also carry the GUI and whatever else you want as a parameter when executing the observer.
But, of course you won't be able to mutate arbitrary global state.
But my point is that it's pretty weird to bring up SML in particular around GUI programming. The GUI framework only example I know of is mGTK and SML/tk which are far from idiomatic and pretty much require you to write imperative OOP code in SML. Meanwhile SML has existed for decades. It's one thing to say "people aren't using this great model we've developed the basics off, please help make it better", but if you wanted to write an idiomatic GUI app in SML today, your first step would be to have to write the GUI framework itself because no one else has. They don't provide any real options even if you fully buy in and want to jump in with what they're saying.
StyledObject -> View -> Text
StyledObject -> View -> ViewContainer -> Button -> ToggleButton -> MyCustomToggleButton
StyledObject -> View -> ViewContainer -> VerticalLayout -> ListView