impl Drawable for MyEntity
void Draw(MyEntity self, Canvas...
Which feels quite natural compared to anemic-entity ECS or naive Composition-over-inheritance like so: class MyEntity {
EntityDrawingComponent drawer
EntityMovingComponent mover;
and of course, over the standard Java/C# OO way class MyEntity : Drawable, Movable, ...
void Move(Vec..)
void Draw(Canvas..)
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.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).
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 completely 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 do not want to leave that open. 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).