Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Yeah, but your argument is kind of circular - we put behavior and data together because we need encapsulation and we need encapsulation because objects have an identity that needs protection, yet those objects need an identity because we are putting behavior and data together, in combination with mutability of course.

Also encapsulation happens quite well in languages that do not have the "private" or "protected" keywords. In Javascript encapsulation happens by closures and local scoping. In Python it happens by convention. Also, take most software developed ever in an OOP style and you'll find plenty of examples of leaky encapsulation (i.e. APIs that leak restricting implementation details), starting with the popular Iterator. IMHO, the best abstractions I know come from languages that are not OOP at all.

I'd also argue that the encapsulation you're talking about doesn't have much to do with OOP in general, only with a particular flavor of it. But that's the problem in all conversations about OOP - take any 2 random people and they'll have different opinions about what OOP is.

For me OOP is about subtyping or more specifically a form of ad-hoc polymorphism that's solved at runtime. It's very convenient for modeling certain kinds of problems for sure - graphical UIs are the best example, or a browser's DOM and even die-hard detractors would find it hard to argue that a Monoid isn't a Semigroup, or that a Set shouldn't be a Function. In fact, objects in OOP do not necessarily need an identity, in which case they are just values, yet you can still put that polymorphism to good use.

But then OOP as implemented and used in mainstream languages is truly awful, being no wonder that people still consider C with half-baked object systems as being something acceptable.



Objects require encapsulation because they have something (mutable state and sensitive data) to protect. Also, I hope its obvious that with identity, you get mutability automatically (just use an immutable map as in Clojure!), and you can't really have meaningful mutability beyond global variables without identity.

Of course, encapsulation can occur at module boundaries, and even when programming with objects, a notion of "internal, package private, or friendship" is often useful. But it is pretty well acknowledged in the PL community that Javascript does encapsulation in the worst way possible (something OOP and FP people can actually agree on).

> But that's the problem in all conversations about OOP - take any 2 random people and they'll have different opinions about what OOP is.

Most people focus on laundry list of pet or hated features when defining OOP, but to me, its all about the objects and if you are thinking in terms of objects in your design. So...

> For me OOP is about subtyping or more specifically a form of ad-hoc polymorphism that's solved at runtime.

I think these are very useful when thinking in terms of objects, but that features like this do not "define objects" but rather that "working with objects make these features desirable." Since you mention it...

> In fact, objects in OOP do not necessarily need an identity, in which case they are just values, yet you can still put that polymorphism to good use.

I would say subtyping is useful for values, but not that anonymous value have somehow become objects since you are manipulating them with subtyping! If I have two values, say 42 and 42, they are the same value no matter how they were computed, stored, retrieved, and so on. They cannot have state (since you can't have state without identity), the different 42s are indistinguishable. In fact, since values are defined solely by their structure, other forms of subtyping might be considered over nominal, like structural, and you might want to abstract over them using type classes. But the reasoning is math-like equational, you aren't really doing OOP at that point from even a design perspective (this is my position, of course it is wide open to debate in the community).

I like C# since it provides both values and objects, and they are adequately separated even if some subtyping still applies to values. But when I am manipulated structs, my design perspective has shifted away from objects; I don't think of them as objects.

> being no wonder that people still consider C with half-baked object systems as being something acceptable.

Back in the 90s, we didn't have much else, C++ still wasn't very trusted; Java was very new. Or if you are referring to C++ and Objective C today, I really couldn't disagree with that.


> I like C# since it provides both values and objects

I don't think the distinction is so clear cut. An immutable List is a value, because it is clearly defined by its structure, yet you need heap-allocated values in C# (so objects) because you need pointers. An immutable List would also implement various interfaces, like Iterable, so polymorphism is useful as well.

I also forgot to say that the polymorphism that we get with OOP is NOT enough. Static languages also need generics and all languages also need type-classes or something similar. Type-classes are different and useful for different use-cases than OOP, because the dictionary is global per class and not per instance. And if it is solved at compile time, like in Haskell or Scala, it also has some performance benefits.

Clojure's protocols for example are pretty neat and get pretty close to type-classes.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: