5 ms·
That's what it's called when you do things like that but what's the reason? From the linked page I read: "Encapsulation is used to hide the values or state of
by robalni 4y ago
That's what it's called when you do things like that but what's the reason?
From the linked page I read: "Encapsulation is used to hide the values or state of a structured data object inside a class, preventing direct access to them by clients in a way that could expose hidden implementation details or violate state invariance maintained by the methods."
So there are two possible reasons here:
1. The access could "expose hidden implementation details". This is not really a reason because it's just saying that you hide something to prevent access in a way that can expose what you hid.
2. The access could "violate state invariance maintained by the methods". Let's say the class has two arrays, `vertices` and `edges`. The state invariance is that they need to have the same number of items (like you have in a polygon). Then why would you make them private? A possible reason could be that it's easy to forget to add an edge if you add a vertex. But why would that be easier to remember if you do it in a member function?
- Jtsummers 4y agoRe 1: The reason is not just to hide access, but also to permit change. Suppose someone implements a data structure using a backing array. Later on they change it to use a b-tree, but users have started directly accessing the backing array (because it's faster than the presented interface, even if just by a function call) and passing around references/pointers to array elements. Oops. You can't make changes anymore, the users are no longer using the intended data structure but a wrapped array. Re 2: Supposing that the two collections have to be the same size, this implies that they get extended at the same time. If they are public, then anyone can add either a vertex or an edge at will. But they are not required (by the interface, only by a verbal contract of sorts) to extend both at the same time. With private members, you present a public interface that ensures both collections are updated simultaneously (or "simultaneously", as a transaction both happen before the method/function/subroutine/procedure/whatever the fuck ends). This makes the class/module author responsible for controlling this invariant, and not the users. Which is the only sane option unless you really like broken contracts and duplicated code scattered throughout a code base.
- robalni 4y ago1. So the reason here to use private is as a way to tell programmers to not use a thing in too many places because then it will be hard to change in all those places if you need to change the private member? 2. First, remember that I am only interested in code that everyone has write access to so even if something is private, everyone can still change it. "This makes the class/module author responsible for controlling this invariant" - does that mean that private is mostly useful together with a rule that only one person (or a few) should change code that belongs to their class, so that that person can keep the invariants in their head and that way avoid breaking them?
- Jtsummers 4y ago1. It's private, only internal routines can use it. You aren't telling anyone to avoid using it, you are constraining where it can be used. You can use it directly in every internal routine if you want, that's not a problem. But no one outside the class/module can directly access it so if you change it (in whatever fashion) then those outside users will not be impacted because they are only dependent on the public interface. Now if you change the public interface, then they are impacted but that's often rare after the initial development effort, in my experience. 2. Forget about people, it's about place. I don't care how many people alter a particular class or module. What I care about is how many places some information has to exist within the code and has to be maintained and synchronized as a result. As a mostly-useless-after-CS101 example, consider a bounded stack. An implementation might have a number (perhaps variable) which describes its limit, an array backing it, and another number indicating where the current "top" of the stack is (in languages where arrays carry their size you don't necessarily need that limit number as a separate thing). If you leave everything public then every user of this bounded stack could directly alter the backing array and change the "top" of the stack, artificially indicating that something had been popped off or incorrectly incrementing beyond the limit. The limit itself could be altered without actually changing the backing array. The backing array could be made smaller or larger without correspondingly changing the limit. All of that would make this data structure useless, because it would be in an arbitrary, likely invalid, state. In order to preserve the invariants of the system (limit == array size, 0 <= top <= limit; as just two of them), you write routines internal to this module (class, whatever) that make sure that when one is changed the others are changed, or that changes are only valid (top can never be larger than limit or less than 0). If users are able to bypass these routines by directly accessing these three member fields of the data structure then to correctly use it they have to preserve all these invariants everywhere they use the data structure. The code is now scattered and contains many duplications. Again, this isn't about people, it's about places and the number of them. If you want to change the internal structure of this bounded stack, you have to change every place that currently accesses the public fields. Or you can be a sane developer, use private fields and public routines that manipulate the state so that it's always in a valid state. Now when you change the internal structure you only have to change those public routines and the private fields, no other place has to be altered. Every use of this bounded stack will look exactly the same as before, just push and pop and some error handling for when the stack is full or empty.
- vanjajaja1 4y agoConsider a class like a HashedLinkedList. This is a linked list which allows direct access to nodes using dictionary look up. It is generally implemented with a LinkedList and Dictionary internally. The expectation is that all elements in the dictionary are in the linked list. Any deviation from this implementation detail will cause invalid state. Making the list or the dictionary public opens you up to situations where consumers of the code modify either datastore independently and corrupt the consistency of the class.