276

Is the visibility private of class fields/properties/attributes useful? In OOP, sooner or later, you are going to make a subclass of a class and in that case, it is good to understand and be able to modify the implementation completely.

One of the first things I do when I subclass a class is to change a bunch of private methods to protected. However, hiding details from the outer world is important – so we need protected too and not just public.

My question is: Do you know about an important use case where private instead of protected is a good tool, or would two options "protected & public" be enough for OOP languages?

Utku
  • 1,922
  • 4
  • 17
  • 19
Adam Libuša
  • 2,067
  • 2
  • 10
  • 14
  • 4
    Possible duplicate of [Why is Clean Code suggesting avoiding protected variables?](http://programmers.stackexchange.com/questions/162643/why-is-clean-code-suggesting-avoiding-protected-variables) – gnat Mar 11 '16 at 09:21
  • 247
    To downvoters: While I also strongly disagree with the OP's premises, I am upvoting this question because it is perfectly coherent and worth answering. Yes, the OP needs to be told why this is wrong, but the way to do that is to *write an answer* (or suggest edits to existing answers), not to downvote just because he hasn't figured it out for himself yet. – Ixrec Mar 11 '16 at 09:51
  • 20
    Derived classes are part of the outer world. – CodesInChaos Mar 11 '16 at 10:40
  • 21
    Don't forget that protected doesn't always mean access is locked to the inheritance hierarchy. In Java, it grants package level access also. – berry120 Mar 11 '16 at 11:49
  • 2
    "sooner or later, you are going to make a subclass of a class and in that case" - Ähm ... no. – Jens Schauder Mar 11 '16 at 13:00
  • 2
    I have voted to close as too board, as this can not be answers in a way that makes sense for ALL object oriented languages. – Ian Mar 11 '16 at 13:15
  • Encapsulation means you have to use less brain ram when you develop. – Mark Rogers Mar 11 '16 at 16:35
  • I see many comments in our code: "// need to make this protected because ...". And I've had change to protected often enough. However, if we (and y'all out there!) simply had better classes - really sticking the Single Responsibility Principle - then other mechanisms and design patterns could more effectively address extendability issues. – radarbob Mar 11 '16 at 18:19
  • 8
    My professor used to say that "There are things I wouldn't tell my children. Those I my private fields." – SáT Mar 11 '16 at 18:52
  • Does `protected` in general imply it is also visible to the package, or is this only a Java thing? – Captain Man Mar 11 '16 at 20:33
  • @CaptainMan C# `protected` implies only accessible to the class and its descendants. Swift doesn't have a `protected`, but its `internal` behaves like the `protected` you describe. [If you wanna read Apple's devblog on it](https://developer.apple.com/swift/blog/?id=11), it actually makes a pretty good case for both why they called it `internal` and why the inheritance-based `protected` is pretty meh – abluejelly Mar 11 '16 at 21:42
  • 2
    It might interest you to learn that Python doesn't have a concept of `private` or `protected`. There is a naming convention for warning callers of your code not to mess with stuff, but there's no actual prevention. This sounds insane if you are coming from a language like Java or C# that does have these and encourages you to use them, but if you give it a chance, you'll find that it's not really that big a deal. Note that this *doesn't* mean that Python programmers recommend leveraging this fact in normal situations. It just means you need to know what is a good idea and what's stupid. – jpmc26 Mar 11 '16 at 22:26
  • @jpmc26 Actually another note with that, it doesn't really warn it so much as Python will not help the coder discover/access/understand any member that starts with.... One underscore? It's been a while. – abluejelly Mar 11 '16 at 22:38
  • @abluejelly Yes, single underscore, double underscore in front for name mangling, double underscore in front and at the end for magic methods. It depends on how you look. If you do `dir(o)` on anything, you'll get everything (even the name mangled attributes and magic methods). I think you're thinking of `from x import *` statements, which don't import attributes on the module starting with an underscore. – jpmc26 Mar 11 '16 at 22:43
  • @jpmc26 Couldda sworn there was a `man` or `help` or something that just printed the `__doc__`, but failed on hidden. But I very well might be thinking `from x import *`. Was a long time ago that I messed with python. – abluejelly Mar 11 '16 at 23:02
  • 1
    don't remove this please... http://steve-yegge.blogspot.com.au/2010/07/wikileaks-to-leak-5000-open-source-java.html – imel96 Mar 14 '16 at 18:46
  • Also related: http://stackoverflow.com/q/18168410/1394393 – jpmc26 Mar 14 '16 at 22:03
  • You can make any protected method be "public" by inheriting the class and in the child make a public method which calls the protected method of its parent. – Marian Spanik Mar 16 '16 at 13:17
  • "In OOP, sooner or later, you are going to make a subclass of a class and in that case, it is good to understand and being able to modify the implementation completely." there's a whole truck-load of assumptions here, and I don't agree with either of them. why do you think this? – sara Mar 16 '16 at 13:24
  • Shouldn't it be "Private by community"? :) – GordonM Mar 18 '16 at 14:37
  • 2
    Python's convention is "we're all consenting adults here". I can honestly say that I've never been in a situation where I've thought, "Boy, I'm *so* glad they made that variable private!" On the other hand I've had several instances where a developer decided that a variable should be private because information hiding!!11!1! And my life was made more difficult. – Wayne Werner Mar 20 '16 at 14:16

17 Answers17

259

In OOP, sooner or later, you are going to make a subclass of a class

This is wrong. Not every class is meant to be subclassed and some statically typed OOP languages even have features to prevent it, e.g., final (Java and C++) or sealed (C#).

it is good to understand and being able to modify the implementation completely.

No, it's not. It's good for a class to be able to clearly define its public interface and preserve its invariants even if it is inherited from.

In general, access control is about compartmentalization. You want an individual part of the code to be understood without having to understand in detail how it interacts with the rest of the code. Private access allows that. If everything is at least protected, you have to understand what every subclass does in order to understand how the base class works.

Or to put it in the terms of Scott Meyers: private parts of a class are affected by a finite amount of code: the code of the class itself.

Public parts are potentially affected by every bit of code in existence, and every bit of code yet to be written, which is an infinite amount of code.

Protected parts are potentially affected by every existing subclass, and every subclass yet to be written, which is also an infinite amount of code.

The conclusion is that protected gives you very little more than public, whereas private gives you a real improvement. It is the existence of the protected access specifier that is questionable, not private.

Sebastian Redl
  • 14,950
  • 7
  • 54
  • 51
  • 34
    +1 for the theoretical scenario of "affected by an infinite amount of code" – Broken_Window Mar 11 '16 at 13:53
  • 13
    Perhaps worth noting as well that the C# designers actually decided to prohibit overriding an inherited method unless it's explicitly marked as `virtual`, for the reasons outlined in this answer. – Will Vousden Mar 11 '16 at 15:05
  • 11
    Or put simply: `protected` is for methods, not for data members. – Matthieu M. Mar 11 '16 at 15:35
  • 7
    I can't find it now, but I remember reading a well written answer from @EricLippert about why MS `sealed` big parts of .net's library and IIRC why he'd've liked to've locked the rest up. The moment you allow 3rd party inheritors to start touching internal values you need to add a huge amount of validation/sanity checks to every method because you can no longer trust any design invariants about the objects internal state. – Dan Is Fiddling By Firelight Mar 11 '16 at 16:05
  • Protected should not be questionable at all. Patterns like Template rely on it and are quite useful – Luis Masuelli Mar 11 '16 at 16:51
  • 1
    @LuisMasuelli He probably means a protected member/method is questionable in the same way that a public one is, i.e. you should always question why it needs to be non-private. – Ixrec Mar 11 '16 at 17:05
  • @Broken_Window In my mind that part was read in the voice of Douglas Adams (with bonus side remarks in HHGttG style). – Mindwin Remember Monica Mar 11 '16 at 17:56
  • @DanNeely - I think it was on SO, [here](http://stackoverflow.com/a/3118480/188535). – detly Mar 12 '16 at 03:26
  • protected is an easy way to make classes testable. Java would benefit from a mechanism that gave test classes access while developing but not when released. – Thorbjørn Ravn Andersen Mar 13 '16 at 12:13
  • Inheritance is vastly overrated. The amount of textbook space devoted to inheritance is grossly out of proportion to the actual need for inheritance. All the arguments in the answers favoring composition over inheritance should be used as antidote for all the intellectual poison of the textbooks. – msw Mar 14 '16 at 04:00
  • 4
    @ThorbjørnRavnAndersen "while developing but not when released" - how on earth is a class supposed to know? Do you really want to compile a test version that is different from the released version when you can't even test the release version? Tests shouldn't need to access private stuff anyway. – Sebastian Redl Mar 14 '16 at 07:51
  • @DanNeely And it also means that more of the class becomes part of the public interface, and thus frozen in time forever. This can severely limit the changes you can make to the base class in the future, and the other classes that depend on that class. It's similar to why so much of the C language is undefined - it gives much more flexibility to the compiler writers and the hardware designers etc., and as long as you keep to the defined parts, you're "safe". Another example of "keep the public interface small". That said, I have yet to see a substantial C app that's 100% defined :D – Luaan Mar 14 '16 at 09:02
  • 1
    @SebastianRedl the JVM knows. And occasionally you need to access very private stuff if e.g. you need to see if the value you need hidden deep in a third party component is set correctly. So, instead of just saying "its useless and there is no need" think outside the box. In a perfect world we don't even need tests. – Thorbjørn Ravn Andersen Mar 14 '16 at 09:15
  • 1
    Well, that's what reflection and makeAccessible() are for. – Sebastian Redl Mar 14 '16 at 10:03
  • @detly That wasn't what I was looking for. The one I was thinking of had Eric advocating for sealing up entire classes because once you let anything be changed by an inheritor you can't trust any bit of the internal state to not be screwed up in any of your functions. – Dan Is Fiddling By Firelight Mar 14 '16 at 10:37
  • @SebastianRedl I think you misunderstood the first quote. The quote indicates that you will need to make at least one subclass from one method. It is not trying to assert that all classes will need a subclass. – Trisped Mar 15 '16 at 00:08
  • @Trisped What do you mean by "make at least one subclass from one method"? I don't understand what making subclasses from methods should be. – Sebastian Redl Mar 15 '16 at 12:27
  • @SebastianRedl Sorry, should have been class, not method. Trying to do too much at once. – Trisped Mar 15 '16 at 16:37
  • "some statically typed OOP languages even have features to prevent it" - This isn't anything to do with a language being "statically typed". PHP, for instance, has the `final` keyword too, preventing class inheritance. – MrWhite Mar 16 '16 at 19:03
  • 1
    @SebastianRedl I don't see how _Not every class is meant to be subclassed_ disproves or is even referring to the statement _In OOP, sooner or later, you are going to make a subclass of a class_ – The Anathema Mar 17 '16 at 16:03
  • @TheAnathema In the context of the claim that `protected` should always be used over `private`, the statement *sooner or later, you are going to make a subclass of a class* has to use "a class" in the sense of "every class", else it is not in support of the claim in the first place. – Sebastian Redl Mar 17 '16 at 22:19
238

Because as you say, protected still leaves you with the ability to "modify the implementation completely". It doesn't genuinely protect anything inside the class.

Why do we care about "genuinely protecting" the stuff inside the class? Because otherwise it would be impossible to change implementation details without breaking client code. Put another way, people who write subclasses are also "the outer world" for the person who wrote the original base class.

In practice, protected members are essentially a class' "public API for subclasses" and need to remain stable and backwards compatible just as much as public members do. If we did not have the ability to create true private members, then nothing in an implementation would ever be safe to change, because you wouldn't be able to rule out the possibility that (non-malicious) client code has somehow managed to depend on it.

Incidentally, while "In OOP, sooner or later, you are going to make a subclass of a class" is technically true, your argument seems to be making the much stronger assumption that "sooner or later, you are going to make a subclass of every class" which is almost certainly not the case.

Ixrec
  • 27,621
  • 15
  • 80
  • 87
  • 14
    I'd toss you more than +1 if I could, as this is the first time `private` ever actually made sense to me. The lib perspective needs to be used more often, otherwise anyone fond of the (C-like) "absolute control, absolute responsibility" coding mentality might flag it as "protects me from myself". Note that I still used `private` previously, I just always felt good documentation and a naming convention like `_foo` to indicate you probably shouldn't be messing with it was equivalent if not better. Being able to deterministically say "nothing will break" is a legitimate, `private`-only feature. – abluejelly Mar 11 '16 at 22:13
  • I originally ignored the case of the code of public libraries and frameworks and thought more or less only in terms of "client code". Optimizing the internal implementation is a good example for my question, though I ask myself, if this really happens in reality (especially when many people recommend a class should not be longer than 1000 lines of code). Generally, I like the Ruby's approach, where private is kind of a recommendation: "Here be dragons, proceed with care". – Adam Libuša Mar 13 '16 at 19:02
  • 9
    @AdamLibuša While this is a much bigger deal if your code is public, it still applies even if you're the author of all of the class' clients. The problem simply changes from certain refactors being *impossible* to certain refactors being tedious and error-prone. Optimization is actually the least common reason for these refactors in my experience (though I mainly do Javascript), usually it's more like a bug that exposed a fundamental implementation flaw which requires restructuring the dependency/call graph of the various internal bits in order to achieve a truly robust fix. – Ixrec Mar 13 '16 at 19:11
  • 5
    ""sooner or later, you are going to make a subclass of every class" is almost certainly not the case." And more to the point, you will almost certainly not, and you SHOULD certainly not, override every function in a class, and change the usage of every data element in a class. Some things should logically be written in stone for the class to have any meaning. – Jay Mar 14 '16 at 04:34
  • 1
    *I'd toss you more than +1 if I could* => That's what we call bounty @abluejelly – Thomas Ayoub Mar 18 '16 at 09:51
  • @Ixrec, I lost you when trying to understand the bolded sentence. And the follow-up sentence. Can you give a more concrete example? Are you saying that if we don't have `private` (only `protected`), we are... unable to add our own class functions/methods with the same name? – Dennis Dec 19 '17 at 16:28
  • @Dennis Well, really the question is can you come up with any change that is backwards compatible in the strictest possible sense without using `private` anywhere. As far as I know, for every possible code change without `private` it's trivial to come up with some client code that would be broken by it. For instance, adding a non-private thing named `foo` becomes backwards-incompatible as soon as anybody writes a subclass with a thing named `foo`. – Ixrec Dec 19 '17 at 23:48
35

Yes, private fields are absolutely necessary. Just this week I needed to write a custom dictionary implementation where I controlled what was put into the dictionary. If the dictionary field were to be made protected or public, then the controls I'd so carefully written could have been easily circumvented.

Private fields are typically about providing safeguards that the data is as the original coder expected. Make everything protected/public and you ride a coach and horses through those procedures and validation.

Robbie Dee
  • 9,717
  • 2
  • 23
  • 53
  • 1
    +1 for a real case example – Broken_Window Mar 11 '16 at 13:58
  • 3
    +1 for "ride a coach and horses through" anything. It's a great phrase that I wish I heard more. – Nic Mar 11 '16 at 19:38
  • 2
    If somebody needs to subclass your class, perhaps he should have access to your safeguards? And if you don't want somebody to change your safeguards to achieve some goal, perhaps don't share the code? It works like this in Ruby - private is more or less of a recommendation. – Adam Libuša Mar 12 '16 at 10:05
  • 3
    @AdamLibuša "Don't share the code"? As soon as you publish any DLL at all, you're sharing the code - all the structures and methods and everything are there for the whole world to see, *especially* with languages that support reflection by default. Everyone can do whatever they want with "your code" - `private` is just a way of saying "don't touch these", and have it enforced within the compiler contract. In systems like .NET, this also has important security implications - you can only touch others' privates when you have full trust (basically the equivalent of admin/root access). – Luaan Mar 14 '16 at 09:06
  • 2
    @AdamLibuša I think your confusion mainly stems from the different OOP approaches different languages took. The root of OOP (as originally defined) is *messaging* - that means that *everything* is private, except for the messages you respond to. In most OOPish languages, this is exposed as "keep your data private" - a way to make the public interface as small as possible. The only way the user (be it a subclass or another class) has to manipulate your class is through the public interface you defined - similar to how you usually use the steering wheel and pedals to drive your car :) – Luaan Mar 14 '16 at 09:09
  • 3
    @Luaan +1 for when it's okay to touch others' privates! – Nigel Touch Mar 14 '16 at 14:30
  • because getting fields using stuff like reflection is so hard. Sorry, but you can already ride a coach, horses and even a train through anything. http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html And I haven't even mentioned how private variables can be circumvented in python where the only thing stopping anyone from accessing anything is just writing two underscores in front of whatever they want to access. At the end of the day, "private" isn't really private. It's "public with a warning sign that this should not be used by the public". – Arnab Datta Jun 09 '16 at 15:59
  • Reflection is part of the standard Java API. How is it anything other than "vanilla"? – Arnab Datta Jun 10 '16 at 13:37
  • I never said reflection was a great idea. I was merely stating the fact that it is there. Private variables in java are not private in the sense people think. It just has a label that says "please don't touch my stuff" on it. There are no safeguards just because someone slapped on a private keyword on to a variable. – Arnab Datta Jun 10 '16 at 18:21
  • Well, I thought it was pretty obvious but apparently not. "Private fields are typically about providing safeguards that the data is as the original coder expected. " <- not true, as I've quite plainly explained. – Arnab Datta Jun 10 '16 at 18:25
  • Nothing "hobby" about Java, and I said nothing about circumventing my own safeguards (why would I want to do that). You claim that any user (another coder who uses the implementation) could be certain that your hashmap implementation was behaving as intended. There is absolutely nothing to stop some random malicious coder from supplying a library that uses your implementation and puts some malicious code in it. The person who uses this library (containing your implementation) can *not* expect it to behave like you intended. They are at the mercy of the library, not you. – Arnab Datta Jun 11 '16 at 02:22
  • Please show me *one* language where using the private access modifier on a variable ensures that it can never be changed by anything other than the original class. I don't have any axe to grind about security. I'm pointing out that access modifiers are there to convey intent, not actual access. There's a huge difference. – Arnab Datta Jun 11 '16 at 12:09
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/41033/discussion-between-robbie-dee-and-arnab-datta). – Robbie Dee Jun 11 '16 at 12:14
  • If code is shared, and you feel it’s a good idea to change the base class I wrote (and sometimes it is), from that point in you have full responsibility for the class. – gnasher729 Apr 07 '21 at 06:56
13

When attempting to reason formally about the correctness of an Object Oriented program it is typical to use a modular approach involving object invariants. In this approach

  1. Methods have associated with them pre and post conditions (contracts).
  2. Objects have associated with them invariants.

Modular reasoning about an object proceeds as follows (to a first a approximation at least)

  1. Prove that the object's constructor establishes the invariant
  2. For each non-private method, assume the object invariant and method precondition hold on entry, then prove that the body of the code implies that the postcondition and invariant hold on method exit

Imagine that we verify an object A using the approach above. And now wish to verify method g of object B which calls method f of object A. Modular reasoning allows us to reason about method g without having to reconsider the implementation of method f. Provided we can establish the invariant of object A and precondition of method f at the call site in method g, we can take the post condition of method f as a summary of the behaviour of the method call. Moreover we will also know that after the call returns the invariant of A still holds.

This modularity of reasoning is what allow us to think formally about large programs. We can reason about each of the methods individually and then compose the results of this reasoning in turn to reason about larger parts of the program.

Private fields are very useful in this process. In order to know that the invariant of an object continues to hold between two method calls on that object, we typically rely on the fact that the object is not modified in the intervening period.

For modular reasoning to work in a context where objects do not have private fields then we would have to have some way to ensure that whatever a field happened to be set to by another object, that the invariant was always re-established (after the field set). It is difficult to imagine an object invariant that both holds no matter what value the object's fields have, and is also useful in reasoning about the program's correctness. We would probably have to invent some complicated convention around field access. And probably also lose some of (at worst even all of) our ability to reason modularly.

Protected fields

Protected fields restore some of our ability to reason modularly. Depending on the language protected may restrict the ability to set a field to all subclasses or all subclasses and same-package classes. It is often the case that we do not have access to all subclasses when we are reasoning about the correctness of an object we are writing. For example, you might be writing a component or library that will later be used in a larger program (or several larger programs) — some of which may not even have been written yet. Typically you will not know if and in what ways it may be sub-classed.

However, it is usually incumbent on a subclass to maintain the object invariant of the class it extends. So, in a language where protect means "sub-class" only, and where we are disciplined to ensure that sub-classes always maintain the invariants of their superclass, you could argue that the choice of using protected instead of private loses only minimal modularity.

Although I have been talking about formal reasoning, it is often thought that when programmers informal reason about the correctness of their code they also sometimes rely on similar types of arguments.

flamingpenguin
  • 2,821
  • 16
  • 12
9

private variables in a class are better than protected for the same reason that a break statement inside a switch block is better than a goto label statement; which is that human programmers are error-prone.

protected variables lend themselves to un-intentional abuse (programmer mistakes), just as the goto statement lends itself to the creation of spaghetti code.

Is it possible to write working bug-free code using protected class variables? Yes of course! Just as it's possible to write working bug-free code using goto; but as the cliche goes "Just because you can, doesn't mean you should!"

Classes, and indeed the OO paradigm, exist to guard against hapless error-prone human programmers making mistakes. The defense against human mistakes is only as good as the defensive measures built into the class. Making the implementation of your class protected is the equivalent of blowing an enormous hole in the walls of a fortress.

Base classes have absolutely no knowledge of derived classes. As far as a base class is concerned, protected does not actually give you any more protection than public, because there's nothing stopping a derived class from creating a public getter/setter which behaves like a backdoor.

If a base class permits un-hindered access to its internal implementation details, then it becomes impossible for the class itself to defend against mistakes. Base classes have absolutely no knowledge of their derived classes, and therefore have no way of guarding against mistakes made in those derived classes.

The best thing a base class can do is hide as much of its implementation as possible as private and put enough restrictions in place to guard against breaking changes from derived classes or anything else outside of the class.

Ultimately, high-level languages exist to minimise human errors. Good programming practises (such as SOLID principles) also exist to minimise human errors.

Software developers who ignore good programming practices have a much higher chance of failure, and are more likely to produce broken unmaintainable solutions. Those who follow good practices have a much lower chance of failure, and are more likely to produce working maintainable solutions.

Ben Cottrell
  • 11,656
  • 4
  • 30
  • 41
  • To downvoter - what could be changed/improved about this answer? – Ben Cottrell Mar 11 '16 at 19:20
  • I didn't down vote, but comparing access level with break/goto? – imel96 Mar 14 '16 at 09:36
  • @imel96 No, comparing the reason why they are avoided, and are discouraged by "Best practise" (particularly for writing *new* code). i.e. A competent programmer would avoid `public` implementation details because it lends itself to unmaintainable code. A competent programmer would avoid `goto` because it lends itself to unmaintainable code. However the real world is such that sometimes you are lost in a terrible mess of legacy code, and have no choice but to use `goto`, and for that same reason you sometimes have no choice but to use public/protected implementation details. – Ben Cottrell Mar 14 '16 at 09:46
  • The severity is different in magnitude, it's incomparable. I could live with code that only have `public` properties/interface, but not with code that only uses `goto`. – imel96 Mar 14 '16 at 10:33
  • 1
    @imel96 Then you either over-estimate the severity of `goto` or under-estimate the severity of having classes whose data is all exposed publicly. Both are common causes of ending up with spaghetti code; it's just that there are a lot more people out in the world who lack understanding of encapsulation and write a lot of bad code with all their data members being `public`. Similarly, there are a lot of legacy codebases out there which already use `goto` and when you work in that code, you tend to be faced with no choice but to continue using it. – Ben Cottrell Mar 14 '16 at 18:12
  • https://en.wikipedia.org/wiki/Considered_harmful is well known and I haven't found anything else raised to that level. Even non-OOP is not considered harmful! – imel96 Mar 14 '16 at 18:43
  • 4
    @imel96 Have you ever actually worked in code which uses `goto` or is it just because you've read articles like that? I understand **why** `goto` is evil because I've spent 2 years working in ancient code which uses it; and I have spent even longer working in code where "classes" have their implementation details leaked everywhere with `public` and `friend` specifiers used as quick/easy/dirty hacks. I don't accept the argument that "exposing implementation details publicly" can't cause an inter-twined spaghetti mess at the same level of severity as `goto` because it absolutely can. – Ben Cottrell Mar 14 '16 at 18:51
4

Inheritable classes have two contracts--one with holders of object references, and with derived classes. Public members are bound by the contract with reference holders, and protected members are bound by the contract with derived classes.

Making members protected makes it a more versatile base class, but will often limit the ways in which future versions of the class might change. Making members private allows the class author more versatility to change the inner workings of the class, but limits the kinds of classes that can be usefully derived from it.

As an example, List<T> in .NET makes the backing store private; if it were protected, derived types could do some useful things that are otherwise not possible, but future versions of List<T> would forevermore have to use its clunky monolithic backing store even for lists holding millions of items. Making the backing store private would allow future versions of List<T> to use a more efficient backing store without breaking derived classes.

supercat
  • 8,335
  • 22
  • 28
4

I think there is a key assumption in your argument that when someone writes a class they don't know who might extend that class down the road and for what reason. Given this assumption your argument would make perfect sense because every variable you make private then could potentially cut off some avenue of development down the road. However, I would reject that assumption.

If that assumption is rejected then there are only two cases to consider.

  1. The author of the original class had very clear ideas for why it might be extended (e.g. it is a BaseFoo and there will be several concrete Foo implementations down the road).

In this case, the author knows that someone will be extending the class and why and therefore will know exactly what to make protected and what to make private. They are using the private/protected distinction to communicate an interface of sorts to the user creating the subclass.

  1. The author of the child class is trying to hack in some behavior into a parent class.

This case should be rare (you could argue it isn't legitimate), and is not preferred to just modifying the original class in the original code base. It could also be a symptom of bad design. In those cases I would prefer the person hacking in the behavior just use other hacks like friends (C/C++) and setAccessible(true) (Java).

I think it is safe to reject that assumption.

This generally falls back to the idea of composition over inheritance. Inheritance is often taught as an ideal way to reduce code reuse however it should rarely be the first choice for code reuse. I don't have a simple knock-down argument and it can be a fairly difficult and contentious to understand. However, in my experience with domain modeling I have found that I rarely use inheritance without having a very clear understanding of who will be inheriting my class and why.

Pace
  • 571
  • 6
  • 17
3

All three access levels have their use case, OOP would be incomplete lacking any of them. Usually you do

  • make all variables/data members private. You don't want someone from outside to mess with your internal data. Also methods that provide auxiliary functionality (think calculations based on several member variables) to your public or protected interface - this is only for internal use, and you might want to change/improve it in the future.
  • make the general interface of your class public. That's what the users of your original class are supposed to work with, and how you think derived classes should look like, too. In order to provide proper encapsulation these are usually only methods (and helper classes/structs, enums, typedefs, whatever the user needs to work with your methods), not variables.
  • declare the methods protected that could be of use for someone who wants to extend/specialize the functionality of your class, but should not be part of the public interface - in fact you usually raise private members to protected when necessary. If in doubt you don't, until you know that
    1. your class can/may/will be subclassed,
    2. and have a clear idea what the use cases of subclassing may be.

And you deviate from this general scheme only if there's a good reason™. Beware of "this will make my life easier when I can freely access it from outside" (and outside here also includes subclasses). When I implement class hierarchies I often start with classes that don't have protected members, until I come to subclassing/extending/specializing them, becoming the base classes of a framework/toolkit and sometimes moving part of their original functionality one level up.

Murphy
  • 821
  • 6
  • 15
1

A more interesting question, perhaps, is why any other type of field than private is necessary. When a subclass needs to interact with the data of a superclass, doing so directly creates a direct coupling between the two, whereas using methods to provide for the interaction between the two allows a level of indirection that can make it possible to make changes to the superclass that would otherwise be very difficult.

A number of languages (e.g. Ruby and Smalltalk) do not provide public fields so that developers are discouraged from allowing direct coupling to their class implementations, but why not go further and only have private fields? There would be no loss of generality (because the superclass can always provide protected accessors for the subclass), but it would ensure that classes always have at least a small degree of isolation from their subclasses. Why is this not a more common design?

Jules
  • 17,614
  • 2
  • 33
  • 63
1

A lot of good answers here, but I'll throw in my two cents anyway. :-)

Private is good for the same reason that global data is bad.

If a class declares data private, then you absolutely know that the only code messing with this data is the code in the class. When there's a bug, you don't have to search all over creation to find every place that might change this data. You know it's in the class. When you make a change to the code, and you change something about how this field is used, you don't have to track down all the potential places that might use this field and study whether your planned change will break them. You know the only places are inside the class.

I have had many, many times that I have had to make changes to classes that are in a library and used by multiple apps, and I have to tread very carefully to make sure I don't break some app that I know nothing about. The more public and protected data there is, the more potential for trouble.

Jay
  • 2,657
  • 1
  • 14
  • 11
1

I think it's worth to mention some dissenting opinions.

In theory, it's good to have controlled access level for all the reasons mentioned in other answers.

In practice, too often when code reviewing, I see people (who like to use private), changing access level from private -> protected and not too often from protected -> public. Almost always, changing class properties involve modifying setters/getters. These have wasted much of my time (code review) and theirs (changing code).

It also annoys me that that means their classes are not Closed for modification.

That was with internal code where you can always change it if you need too. The situation is worse with 3rd party code when it's not so easy to change code.

So how many programmers think it's a hassle? Well, how many are using programming languages that don't have private? Of course, people are not just using those languages because they don't have private specifiers, but it helps to simplify the languages and simplicity is important.

Imo it's very similar to dynamic/static typing. In theory, static typing is very good. In practice, it only prevents like 2% of errors The Unreasonable Effectiveness of Dynamic Typing .... Using private probably prevents error less than that.

I think SOLID principles are good, I wish people care about them more than they care about creating a class with public, protected and private.

imel96
  • 3,488
  • 1
  • 18
  • 28
  • 1
    If you need to change 3rd party code when using it, either it is not well designed, either you are not reusing it well. You can always reuse a non-abstract class by encapsulating it, but in practice you hardly ever need to subclass it. – Little Santi Mar 16 '16 at 23:26
0

I'd also like to add another practical example of why protected is not enough. At my university the first years undertake a project where they have to develop a desktop version of a board game (that later an AI is developed for and it is connected to other players over a network). Some partial code is provided to them to get them started including a testing framework. Some of the properties of the main game class are exposed as protected so that the test classes that extend this class have access to them. But these fields aren't sensitive information.

As a TA for the unit I often see students simply making all their added code protected or public (perhaps because they saw the other protected and public stuff and assumed they should follow suit). I ask them why their protection level is inappropriate, and many don't know why. The answer is that the sensitive information that they are exposing to subclasses means that another player can cheat by simply extending that class and accessing the highly sensitive information for the game (essentially the opponents hidden location, I guess similar to how it would be if you could see your opponents pieces on a battleships board by extending some class). That makes their code very dangerous in the context of the game.

Other than that, there are many other reasons to keep something private to even your subclasses. It might be to hide implementation details that could mess up the correct working of the class if changed by someone who doesn't necessarily know what they are doing (mostly thinking about other people using your code here).

J_mie6
  • 109
  • 2
  • 2
    I don't understand. Unless players are dynamically extending classes while the game is running, how could this be used to cheat? This would imply that you're importing untrusted code into your codebase. If you are saying that you giving students compiled classes and preventing them from cheating in their assignment by modifying implementation details, setting a protection level isn't going to make the assignment any more secure. Students can decompile libraries or use reflection to their advantage. This of course depends on the level of enforcement you are after. – Sam Mar 13 '16 at 00:30
  • @sam Generally code should be written with the assumption that whoever modifies it next won't need to know the entire codebase inside out. That could even be the original author at times (time passing, lack of sleep...). Cheating could be students being given skeleton code to flesh out, and changing logic they shouldn't touch. – Phil Lello Mar 16 '16 at 14:17
0

Private methods/variables will generally be hidden from a subclass. That can be a good thing.

A private method can make assumptions about parameters and leave sanity checking to the caller.

A protected method should sanity check inputs.

Phil Lello
  • 875
  • 6
  • 14
-1

One of the first things I do when I subclass a class is to change a bunch of private methods to protected

Some reasoning about private vs. protected methods:

private methods prevent code reuse. A subclass cannot use the code in the private method and may have to implement it again - or re-implement the method(s) which originally depend on the private method &c.

On the other hand, any method which is not private can be seen as an API provided by the class to "the outer world", in the sense that third-party subclasses are considered "outer world" too, as someone else suggested in his answer already.

Is that a bad thing? - I don't think so.

Of course, a (pseudo-)public API locks the original programmer up and hinders refactoring of those interfaces. But seen the other way around, why should a programmer not design his own "implementation details" in a way that's as clean and stable as his public API? Should he use private so that he can be sloppy about structuring his "private" code? Thinking maybe that he could clean it up later, because no one will notice? - No.

The programmer should put a little thought into his "private" code too, to structure it in a way that allows or even promotes reuse of as much of it as possible in the first place. Then the non-private parts may not become as much of a burden in the future as some fear.

A lot of (framework) code I see adopts an inconsistent use of private: protected, non-final methods which barely do anything more than delegating to a private method is commonly found. protected, non-final methods whose contract can only be fulfilled through direct access to private fields too.

These methods cannot logically be overridden/enhanced, although technically there's nothing there to make that (compiler-)obvious.

Want extendability and inheritance? Don't make your methods private.

Don't want certain behavior of your class altered? Make your methods final.

Really cannot have your method called outside of a certain, well-defined context? Make your method private and/or think about how you can make the required well-defined context available for reuse through another protected wrapper method.

That's why I advocate to use private sparingly. And to not confuse private with final. - If a method's implementation is vital to the general contract of the class and thus is must not be replaced/overridden, make it final!

For fields, private is not really bad. As long as the field(s) can be reasonably "used" via appropriate methods (that's not getXX() or setXX()!).

JimmyB
  • 153
  • 6
  • 2
    -1 This doesn't address the `private` vs `protected` original question, gives mistaken advice ("use `private` sparingly"?) and goes against the general consensus on OO design. Using `private` has nothing to do with hiding sloppy code. – Andres F. Mar 11 '16 at 19:24
  • 3
    You mention that a class has an API, but don't seem to make the connection that the user of the API does not want to be burdened with details that they don't need to know. The ideal situation for the user of a class is for the interface to contain only the methods they need, and nothing else. Making methods `private` helps to keep the API clean. – Ben Cottrell Mar 11 '16 at 19:33
  • @AndreasF. My advice is certainly not mistaken, but your comment leads me to ask: Then when do you use protected? And yes, most programmers do use private to make their life easier without fully thinking it through. – JimmyB Mar 12 '16 at 14:57
  • @BenCottrell You say "the methods they need", and that is the problem. How do you know which methods a future subclass may want to reuse or override? Apparently I did not make myself clear enough because from the comments and downvotes I feel that my point didn't quite get through. I think I'll let my answer stand as it is for now though because elaborating would mainly repeat the other answers already given. If someone got my point and has a suggestion for improvement I'd love to edit it in. – JimmyB Mar 12 '16 at 15:06
  • @AndreasF. How does my answer not address the question "is private useful", when I state in which case it is or is not useful? – JimmyB Mar 12 '16 at 15:16
  • @HannoBinder It is the responsibility for somebody writing a class to decide how that class can and cannot be used so they can prevent it from being mis-used in ways which had not been originally intended. The author of a class will always know which methods a future subclass can reuse or override because it is their responsibility as designer to ensure that class is well behaved when it is reused and when those elements of that class are reused and overridden. – Ben Cottrell Mar 12 '16 at 15:18
  • @BenCottrell I fully agree with you. Except that I'd say "the author of a class **should** know...". And from my experience, people often do *not* correccly anticipate possible valid future uses of their classes. That's e.g. when a class will output to console or files, but just cannot be made to output to a network stream, through subclassing or any other means. – JimmyB Mar 12 '16 at 15:24
  • 1
    @HannoBinder I agree that there are plenty of classes out there which suffer from rigidity, however flexibility and code reuse are much less important than encapsulation and long-term maintainability. Consider your case where all classes have protected members and derived classes can mess about with any implementation details they desire; how do you reliably unit test those classes knowing that anything in any part of yet-unwritten code could cause that code to fail at any time? how many such "hacks" could the code take before it all degenerates into a big ball of mud? – Ben Cottrell Mar 12 '16 at 15:49
  • 1
    @BenCottrell I tend to argue in the opposite direction: Each method has a *contract* to fulfil. How it goes about that does not relly matter, so as long as the contract remains fulfilled anyone may override my method with any novel implementation he sees fit. My tests test my code. Future extensions must be tested by whoever is responsible for them, in addition to my tests. Of course, altering a method's contract in a subclass is not a valid change and whoever implements the override must consider that or things break. Yet, in Java, we have `final` that can be used in combination with any – JimmyB Mar 12 '16 at 17:23
  • 1
    visibility, and I ecourage people to not use `private` when in fact they mean `final`. – JimmyB Mar 12 '16 at 17:25
  • 2
    Oh, you said "members". What I'm saying is referring to *methods* only. Member variables (fields) is a different story, where privacy is much more justified. – JimmyB Mar 12 '16 at 18:12
  • 2
    The nomenclature in the discussion is all over the place because it is not specific to a particular language. "Member" in C++ can be data, function, type, or template. – JDługosz Mar 12 '16 at 21:05
  • 1
    @HannoBinder indeed, at this point I think we have been talking past each other - I inferred from the question that the issue is around data members/member variables rather than Methods. I have no issue around protected methods, and I find that classes which adhere to "SOLID" (particularly SRP) tend to have few methods which are either protected or private anyway. – Ben Cottrell Mar 12 '16 at 22:13
-1

"private" means: Not intended to be changed or accessed by anyone except the class itself. Not intended to be changed or accessed by subclasses. Subclasses? What subclasses? You are not supposed to subclass this!

"protected" means: Only intended to be changed or accessed by classes or subclasses. Likely deduction that you are supposed to subclass, otherwise why "protected" and not "private"?

There's a clear difference here. If I make something private, you are supposed to keep your dirty fingers off it. Even if you are a subclass.

gnasher729
  • 42,090
  • 4
  • 59
  • 119
-1

Do you know about an important use case where private instead of protected is a good tool, or would two options "protected & public" be enough for OOP languages?

Private: when you have something that will never be useful for any subclass to call or override.

Protected: when you have something that has a subclass-specific implementation/constant.

An example:

public abstract Class MercedesBenz() extends Car {
  //Might be useful for subclasses to know about their customers
  protected Customer customer; 

  /* Each specific model has its own horn. 
     Therefore: protected, so that each subclass might implement it as they wish
  */
  protected abstract void honk();

  /* Taken from the car class. */
  @Override
  public void getTechSupport(){
     showMercedesBenzHQContactDetails(customer);
     automaticallyNotifyLocalDealer(customer);
  }

  /* 
     This isn't specific for any subclass.
     It is also not useful to call this from inside a subclass,
     because local dealers only want to be notified when a 
     customer wants tech support. 
   */
  private void automaticallyNotifyLocalDealer(){
    ...
  }
}
Arnab Datta
  • 191
  • 8
  • 2
    *when you have something that will never be useful for any subclass to call or override* – And this is something that you, in my opinion, never know in advance. – Adam Libuša Mar 18 '16 at 13:02
  • Well, I might also need to press the reset button on my CMOS. But the default assumption is that I won't really need it, and therefore it is put inside the chassis. The same goes for methods. You make it protected if the subclass absolutely needs to reimplement/call it (see: honking). You make it public if other parties need to call it. – Arnab Datta Mar 18 '16 at 23:15
-2

It was hard for me to understand this matter, so I'd like to share a piece of my experience :

  • What is the protected field? It's nothing more than a field, that can't be accessed outside a class, i.e. publically like this: $classInstance->field. And the trick that it's "this is it". Your class' childrens will have a full access to it, because it's their rightful internal part.
  • What is the private field? It's a "true private" for your very own class and your very own implementation of this class. "Keep out of reach of the children", just like on a medicine's bottle. You will have a guarantee that it's unoverridable by your class' derivatives, your methods - when called - will have exact what you've declared

UPDATE: a practical example by a real task I've solved. Here it is : you have a token, like USB or LPT(that was my case), and you have a middleware. The token asks you for a pincode, opens up if it's correct and you can send encrypted part and a number of key to decipher. The keys are stored in token, you can not read them, only use them. And there were temporary keys for a session, signed by a key in a token, but stored in a middleware itself. The temp key were not supposed to leak eveywhere outside, just to exist on a driver level. And I used a private fields to store this temporary key and some hardware-connection-related data. So no derivatives were able to use not just a public interface, but also some protected "handy" subroutines I've made for a task, but were unable to open a strongbox with the keys and HW interaction. Makes sense?

  • sorry guys! just messed them up - updating my answer =) THANKS! I was in a hurry and mistyped =) – Alexey Vesnin Mar 11 '16 at 23:10
  • 2
    I think the OP is aware of the differences between the two protection levels, but is interested in why one should be used over the other. – Sam Mar 13 '16 at 00:32
  • @Sam please take a deeper reading of my answer. They are **completely different** types of field! the **only** thing they have in common is that they both can not be referenced publically – Alexey Vesnin Mar 13 '16 at 01:18
  • 2
    I'm not sure what you are referring to. I'm aware of the differences between private and protected. Perhaps you mis-understood what I meant by protection levels? I'm referring to 'access level's. I was trying to point out that while your answer isn't bad, it doesn't directly address the question. The OP appears to know what both protected/private/public mean, but isn't sure under what circumstances they would want to choose one over the other. This may be way you are been voted down (not by me). – Sam Mar 13 '16 at 06:45
  • @Sam I think I've got your point - added a practical case from my real practice/experience. Is it what's missing on your point? – Alexey Vesnin Mar 13 '16 at 15:01