4 ms·
Let's be precise about what definition of OOP we're each using. In college, I (and I'm sure many others here) learned that OOP was about "abstraction, encapsul
by kibwen 2y ago
Let's be precise about what definition of OOP we're each using.
In college, I (and I'm sure many others here) learned that OOP was about "abstraction, encapsulation, inheritance, and polymorphism".
But in practice, looking at the history of programming paradigms in industry, it seems like the real success of OOP was in dragging us away from "it's fine for mutable state to be global and/or scattered willy-nilly throughout your code" and towards "mutable state should be localized, tightly scoped, and/or coupled to the code that will be mutating it". Being generous to the academic definition, we could say that the only pillar of OOP that really mattered was encapsulation.
And by that definition, since Rust abhors global mutable state (but not mutation in general, as a functional language might do), it's not unreasonable to say that Rust, even if it doesn't have "objects" as Java or Smalltalk define them, still hews to the most useful parts of OOP.
- logicchains 2y ago> "mutable state should be localized, tightly scoped, and/or coupled to the code that will be mutating it Typical enterprise OOP did the opposite of this, coupling state to unrelated code via inheritance. To quote the creator of Erlang, when you want the banana it gives you the whole forest.
- mrkeen 2y ago> towards "mutable state should be localized, tightly scoped, Ironically, the way to do actual encapsulation / localized-mutable-state is to just use stack variables - the C way. Fields (what OOP added) are leakier and less localized than stack variables.
- kibwen 2y ago> just use stack variables - the C way The problem is that C doesn't offer any resistance to using globals rather than stack variables, which led to much of the mess that the OOP revolution of the 80s was supposed to address. For every C program that eschews globals, you have a Toyota Camry, whose control systems famously contained "10,000 global variables" https://news.ycombinator.com/item?id=9643204 https://news.ycombinator.com/item?id=9643204
- mrkeen 2y ago> The problem is that C doesn't offer any resistance to using globals rather than stack variables Nor is there any resistance to writing 'public static' on a field anywhere in Java land. If that's a problem, you have to throw out most languages.
- trealira 2y agoC still has fields in structures; you just have to pass a structure as the argument to a function. As long as you're okay with syntax like "self->field" or "self.field" (given a parameter called "self"), you can still kind of do OOP, just that no fields are private.
- mrkeen 2y ago> no fields are private. Who needs the private keyword when C has better encapsulation than Java? -- foo.h typedef struct Bleh Bleh_t; Bleh_t *construct(int i); int getFoo(Bleh_t *bleh); -- main.c #include "foo.h" void main() { Bleh_t *bleh = construct(3); // int i = bleh->foo; int i = getFoo(bleh); } The commented-out line above will not compile, because the internals of Bleh_t are not exposed.
- trealira 2y agoThat's true, and many libraries do this. However, it comes at the cost of an unnecessary heap allocation that wouldn't otherwise be necessary if not for this encapsulation. If you want to do this, but allocate on the stack, you have to do something like this: typedef struct Bleh Bleh_t; size_t get_bleh_size(); void init_bleh(Bleh_t *, int); int main(void) { const size_t bleh_size = get_bleh_size(); Bleh_t *const bleh = alloca(bleh_size); init_bleh(bleh, 3); const int i = getFoo(bleh); } If you rewrite "init_bleh" to return the pointer it receives as the first parameter, you could hide it behind a macro: #define make_stack_bleh(i) init_bleh(alloca(get_bleh_size()), (i)) Used like this: Bleh *const bleh = make_stack_bleh(x); One advantage of this approach is that you could change the layout of a Bleh without recompiling the other object files, as your compiled code makes no assumptions about the size or the layout of the struct (i.e. the field offsets into a struct aren't hardcoded into the machine code emitted).
- zamalek 2y ago> In college, I (and I'm sure many others here) learned that OOP was about "abstraction, encapsulation, inheritance, and polymorphism". This is what I was referring to. A problem that follows is that many of the Go4 patterns solve problems that OOP causes in the first place (obviously many others are universal).