5 ms·
Haven't classes -- as things which house methods and fields together -- gone out of fashion? I think the same thing has happened with inheritance. The ontologi
by ogogmad 4y ago
Haven't classes -- as things which house methods and fields together -- gone out of fashion? I think the same thing has happened with inheritance.
The ontological problem of "does the knife cut the cucumber" or "does the cucumber get cut with the knife" seems serious. The "is-a" relationship is also problematic, because does a square inherit both from rhombus and parallelogram?
- Cyberdog 4y agoWhat on Earth makes you think it's gone out of fashion? Pretty much all of the most widely-used languages have classes or analogues, if not full OOP.
- ogogmad 4y agoI thought that privileging the first argument of a function, which is all that separates a method from a function, was understood to be an ugly hack. I thought that this was acknowledged now, and only legacy languages are stuck with it. Julia, Rust and Go don't do this. So it's going out of fashion and becoming legacy. IOW, there was never really a difference between obj f(obj); and class obj {obj f();} so the whole idea was a mistake. Likewise, obj.f() should be synonymous with f(obj) and the fact that in some languages it's not is evidence of a poorly thought-out abstraction. See multiple dispatch for the death blow. There's also a discussion elsewhere here about operator overloading, and how arithmetic operators don't behave like methods.
- germandiago 4y agoFrom a mathematical point of view it can seem like that. But now pick a language like Nim, whcih also has a crazy regex to match symbol equality, and unigorm call syntax etc. and the IDE completions are much harder to find.
- Jtsummers 4y ago> I thought that privileging the first argument of a function, which is all that separates a method from a function, was understood to be an ugly hack. I thought that this was acknowledged now, and only legacy languages are stuck with it. Julia, Rust and Go don't do this. So it's going out of fashion and becoming legacy. [emphasis added] What? Go has methods which "privilege" the first argument to functions: https://go.dev/tour/methods/1 https://go.dev/tour/methods/1 func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) } Though it moves the argument out of the argument list and between the func keyword and method name. Rust also has a notion of methods: https://doc.rust-lang.org/rust-by-example/fn/methods.html https://doc.rust-lang.org/rust-by-example/fn/methods.html Were you thinking of other languages?
- mappu 4y agoIn Go you can assign this "method" to a func(v Vertex) float64 and it will run just fine: https://go.dev/play/p/NBS4Fc3r0w- https://go.dev/play/p/NBS4Fc3r0w- It really is just syntax sugar,
- lifthrasiir 4y agoYou can have multiple `f` with different "arguments" (if you consider a receiver a part of arguments) without the full multimethod, which is actually pretty hard to get it right and only one language out of your examples (Julia) does that. Other two languages (Rust and Go) fully retain classes, slightly obscured to fit with traits and interfaces respectively.
- jakelazaroff 4y agoobj.f() shouldn't necessarily be synonymous with f(obj) though. How would the latter case handle private fields, for example?
- ogogmad 4y agoYou'd use a module to hides things. Some OOP languages conflate modules (which do information-hiding) with private fields in classes. If you think that `obj.f()` and `f(obj)` should mean different things, then your reasoning is likely faulty.
- jakelazaroff 4y agoTo clarify, I’m talking about private fields in each object/struct. You could say all functions defined in the same module get access to private struct fields. That works until you want a more specialized version of some of those functions — essentially, a different module that has access to protected fields. Here’s another example. You’re writing a function `g` that accepts an object of type `Foo` and calls function `f` on it. You have a default implementation of `f`, but you also want to let the caller supply their own implementation. If you have some way of attaching behavior to a type — classes, typeclasses, etc — this is trivial. If not, your function has to explicitly ask for every single function from the caller.
- still_grokking 4y ago> You'd use a module to hides things. And than you need functors and existential types to recreate classes… ;-) Your reasoning is likely faulty if you don't see that OOP is a very advanced and great module system. The only problem with OOP is that it's often misused for other things that aren't modules. But that's a different story.
- theteapot 4y ago> You'd use a module to hides things. Some OOP languages conflate modules (which do information-hiding) with private fields in classes. And you can instantiate multiple instances of these "modules"?
- imtringued 4y agoI wish I had your problems.
- newobj 4y agoOnly the misapplications you give examples of have gone out of style, I’d say.
- ogogmad 4y agoHow do you know when it's a misapplication? What do these constructs actually model?
- deleted 4y ago[deleted]
- Banana699 4y agoState Machines. Objects are supposed to model state machines, each mutating method is a transition event that takes the current state and any number of arguments and transition the state machine to a new state. In very simple words, each object in an OOP program is a virtual computer, its class define the instruction set. "Objects are a recursion on the notion of computer itself" --Alan Kay
- ogogmad 4y agoSounds profound, but I don't know why you'd want to use this metaphor heavily.
- astrange 4y agoState encapsulation is useful insofar as, if you wanted to write a proof that those pieces of state were only ever set correctly (eg using a statechart), you can now do that. OOP languages never actually include this because nobody seems to particularly care if their code actually works.
- ok_dad 4y ago> The ontological problem of "does the knife cut the cucumber" or "does the cucumber get cut with the knife" seems serious. Kinda both! The knife (aka: the "Cutter") can perform a "Cut" action on any object (aka: the "Cutable"), but the Cutable objects have to receive the Cut action and determine if the Cutter has enough "Cutter.Strength" to Cut the Cutable. I think the failure of OOP is applying it to things that aren't appropriate or creating a Factory pattern that causes over-abstraction. OOP in itself isn't bad, much like PHP or Windows has their place even though they get shit on all the time, but the lack of care applying OOP (or any other pattern or architecture) is the bad part.
- deleted 4y ago[deleted]
- mftb 4y ago> Haven't classes -- as things which house methods and fields together -- gone out of fashion? There's your issue right there, "fashion". If we put aside fashion for a moment, we'll notice that all of the most heavily used languages are multi-paradigm. Trying to be purely-OOP or purely-functional, is intellectually and academically appealing, but not very pragmatic for a general-purpose language. In the end fashion comes and goes, but engineering remains.
- hot_gril 4y agoClasses are a good feature to have, provided you aren't forced to use them and you don't go overboard with OOP (cough Java). Any equivalent becomes rough in some common use cases. I might be wrong, but it seems like Python approached it from that direction, with Py2 having half-baked classes. Classes are also nicer to deal with in dynamically-typed languages, or at least ones with very smart automatic static typing. You don't get stuck dealing with all that pedantry. Btw, your example works fine in OOP. It'd be parallelogram -> rhombus -> square. But yes there are examples of it not working well.
- ogogmad 4y agoAh, I meant rectangle instead of parallelogram. Rectangle, rhombus, square. What's the inheritance hierarchy?
- hot_gril 4y agoYeah, that's an example of inheritance not working. Python does support multi-inheritance, but it's messy. Best you can do is interfaces instead of subclasses. Honestly can't remember the last time I've subclassed something and actually cared to inherit methods/variables.
- rileyphone 4y agoThat's because there are two separate types of inheritance that often get conflated in popular OOP languages: subclassing (implementation inheritance) and subtyping (specification inheritance). The 'types' here are the interfaces in typical OOP languages, though their (especially Java) failure to orient types around them create much of the pain developers experience. See https://www.cs.utexas.edu/~wcook/papers/InheritanceSubtyping90/CookPOPL90.pdf https://www.cs.utexas.edu/~wcook/papers/InheritanceSubtyping...
- imtringued 4y agoNo language on earth does data dependent typing.
- ogogmad 4y agoErratum: Parallelogram should be rectangle. Thanks, newobj.
- crabmusket 4y ago> Haven't things which house methods and fields together gone out of fashion? Rust's structs have methods and fields together, and that seems very much in fashion! But, I wish that using OOP constructs to model ontologies would go out of fashion faster. The examples you pose are so abstract as to have no correct answer, because the correct answer depends on the needs of the software. Cucumber/knife could be modeled in a thousand different ways depending on whether you're making The Sims, a recipe website, or the firmware for a robot chef. "is-a" is indeed problematic, because "is" is a linguistic construct that can have different meanings, and there's never just a single "is-a" relationship. I'd go out on a limb and say you should never need classes for Square, Rectangle, etc; just make a Polygon that is a closed collection of points, and be done with it. But that doesn't stop OOP education (from web tutorials to university courses) from teaching students to think about ontologies first and requirements second. These are problems with the way OOP is often used, and with the language features that encourage this kind of usage. But I don't think it's necessary to say that classes in their entirety are an antipattern.
- imtringued 4y agoYes your job is to get things done not to care about ontological purity. The problem with ontological purity is that it would need complicated features that aren't worth bothering with. Oval vs circle for example is a classic case of parameter dependent typing yet no language on this planet has objects whose type changes as it's data changes.
- astrange 4y agoDependent type systems like Idris do have that.
- valenterry 4y ago> Yes your job is to get things done not to care about ontological purity. It is part of the job since it changes how (well) things get done. > no language on this planet has objects whose type changes as it's data changes. Yes there are. You might want to look into dependently typed languages.
- 4y ago
- imtringued 4y agoNo they haven't. Everyone still loves their type dependent namespaces. Just look at the ugliness of Haskell records where every field is a global function inside a module.