An Object-Oriented Language for the '20s
I love how rust does interfaces (traits) and allows implementing <i>outside</i> the type. It feels much more natural to create a subsystem on the side without tangling it into other subsystems. E.g. to create a separate rendering subsystem for a game entity you simply<p><pre><code>    impl Drawable for MyEntity
      void Draw(MyEntity self, Canvas...
</code></pre>
Which feels quite natural compared to anemic-entity ECS or naive Composition-over-inheritance like so:<p><pre><code>    class MyEntity {
      EntityDrawingComponent drawer
      EntityMovingComponent mover;
      </code></pre>
and of course, over the standard Java/C# OO way<p><pre><code>    class MyEntity : Drawable, Movable, ...
      void Move(Vec..)
      void Draw(Canvas..)
</code></pre>
With this type of declaration, I'm forced to mix the code for my different subsystems making it not just likely but inevitable that someone eventually ties these subsystems together.<p>In general, if I were to design a "better" OO language now; i'd make sure to make it almost not OO at all. I'd allow subclass polymorphism, but no virtual methods or classes. Only interfaces/traits and abstract classes. I'd very clearly separate data types from identity types at the language level (which aren't just a difference betweeen stack and heap as with C# structs and classes).<p>I'd want the bare minimum of functional niceness: enumerations and pattern matching which check for exhaustion. Having that in a lanugage easily lets the developer use different implementation for two <i>completely</i> different cases: open and closed polymorphism sets. OO is great when you don't know what variants might exist, but it's useless when you DO want to control it.
If I as a developer know that the set of Payment options are Credit/Cash/Invoice - then I want it exhaustively checked. I deliberatel <i>do not want to leave that open</i>. I want to be able to switch on the closed set of 3 cases, and be warned if I fail to check a case. I want to be able to do this without inverting the logic like and calling into the unknown like paymentMethod.HandlePayment(order).