5 ms·
> Classes are not a design inevitability, but just one way of managing state What "Classes" are is a tragedy of things. Classes are closures, with a syntactic
by Supermancho 5y ago
> Classes are not a design inevitability, but just one way of managing state
What "Classes" are is a tragedy of things.
Classes are closures, with a syntactic form that allows for nested composition. This is a particularly brittle form and these qualities are found in all languages with Classes. Language maintainers, as they currently exist, have failed to concede that this is a bad idea, because "it works good enough for lots of cases". This has hurt the industry by creating a culture that can only support the view that "all code is ugly". Given the choices, the variability in how code evolves randomly to deal with choices made under these conditions, is unsurprising.
Why? Because Classes are a good feature that has been misrepresented as a compositional tool instead of a syntactical shortcut and nobody is dealing with the gravity of that...given the amount of history, industry, effort, et al based around supporting their faux necessity, who could be blamed for not raising a stink? And why is there a "new" keyword in 2022? Python gets this right.
Almost every language ends up heaping additional syntax for behavior that is either compiler added (eg php/rust traits, ruby aspects) a meta-language (eg Java aspects, php attributes, various C++ impls, ES6 javascript classes), or a straight mixin syntax (Python decorator). This alone, is obvious that the support for composition is a major problem that has both been neglected, then mishandled by heaping on the same mistakes. Interfaces, were a particularly laughable solution, which has made the problem worse by tying that limited form of composition with reflection.
> Languages that mostly avoid mutable state don't tend to have object systems, for instance.
They do, in the form of closures. How infrequently composition-by-nesting is used in functional languages is telling (basically the inverse of nonFP languages).
- tsimionescu 5y agoClasses are closures just as much as closures are classes (as Java showed). What classes are at their most core is bundles of behavior, possibly with encapsulated state, and usually some way to decide at runtime which of a family of classes' behavior to use. Closures are naturally tied to 1 single behavior (though of course you can invent ad-hoc methods of extending that, such as a "methodName" parameter, but no one ever does this in practice). This is the reason why classes and interfaces actually exist in some form or another in all useful languages today. For example, Go has structs with methods + interfaces, Rust has structs + traits, OCaml has modules + module types (well, it also has classes, but I understand those are less popular), Haskell has data types and type classes, and on and on, JavaScript has objects + dynamic name resolution. The one idea from classic OOP that has turned out to mostly be a dead-end is implementation inheritance + subtyping. This is basically the only class feature you'll only find in specific OO concepts, and basically all modern guides tell you to avoid it.
- biorach 5y ago> and basically all modern guides tell you to avoid it. If only... There's still a thriving OO-heavy mindset in much of the Java ecosystem, but less evangelical that it used to be. In other languages... Inheritance tends to be de-emphasised compared to a decade ago, thankfully. I rarely see advice to avoid it - instead moderation is advised. I think the main problem is that it is hard to explain to a learner what the pitfalls are with inheritance-heavy OO design except in the most general terms. It's something that can be quite useful when used judiciously, in the right context, but knowing when this is requires experience.
- sirwhinesalot 5y agoClosures are the superior mechanism though, you can implement classes plus all the crazy decorators / metaclasses / mixins / etc. The reverse is true of course but in the dumbest way possible. A closure-based implementation of a class is just a function that returns a structure full of closures (an interface if you will) all with the same shared state. But now because a class is just a function, you can do all kinds of crazy things with it, the "constructor" can even pick and choose which functions to use to implement the interface at runtime, while retaining full typesafety. Classes are not just unnecessary, they're a bad abstraction.
- tsimionescu 5y ago> Classes are not just unnecessary, they're a bad abstraction. And yet, there are approximately 0 examples of the "closure-backed classes" example you give, while every vaguely popular language except C has some variant of polymorphic classes, from StandardML to Lisp. Your closure example is not used in any langauge because it's extremely un-ergonomic. If the langauge doesn't have some kind of concept of "interface" (abstract class, type class, trait, structural typing etc), then you'll either miss polymorphism (return a single specific type), or be too dynamic (return an object that could do anything). It also risks being inefficient if you try to naively add function pointer members to each object to support runtime dispatch. The closure-based alternative also obscures the relationship between product data types (structs/record types) and classes (structs with methods). Closure-backed classes are a neat experiment, but just like manual virtual table management in C, they are not a realistic solution to the problems that classes address, if you can possibly avoid them.
- weavejester 5y ago>> Languages that mostly avoid mutable state don't tend to have object systems, for instance. > They do, in the form of closures. You can build an object system from closures, certainly, but I wouldn't say closures are objects by themselves. An closure lacks inbuilt messaging, which is usually considered a requirement for an object.
- Supermancho 5y ago> You can build an object system from closures, certainly, but I wouldn't say closures are objects by themselves. This raises 2 issues. 1. Is a closure an object? An "object" is conceptual, not based on a specific algorithm. Then you mention a capability of messaging being a requirement for the Object concept. This is where arguments start going off the rails in casual language discussion because people combine the idea of what a language can do (capability), what a language was designed to do (designed-for) with the supporting ecosystem, and what's possible in a turing machine by virtue of what other languages provide (in capability/designed-for). You can message to other closures via methods, just like the vast majority of languages currently support. This kind of messaging is not async, which seems like a stupid cheat on the idea of a message, but it makes sense once you start running lots of synchronous objects with independent lifecycles, locations, and identity characteristics...then you realize the quick cheat costs you in large distributed systems while being very efficient in smaller systems, imo.
- weavejester 5y agoAlan Kay defined object-orientated programming as having messaging, state hiding, and late binding. I think the ship has sailed on the last one, but the first two properties hold true for at least all the object orientated languages I'm aware of. A closure lacks messaging by default, so it's not an object. You can certainly make an object from a closure, and in an object orientated language a closure may be itself represented by an object; but responding to messages is not an inherent property of a closure. It's not useful to say that all languages have all features; the line has to be drawn somewhere. Being able to theoretically write an object system for a language doesn't make the language object orientated.