Why have private fields, isn't protected enough?

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?

1,922 4 4 gold badges 18 18 silver badges 20 20 bronze badges asked Mar 11, 2016 at 9:17 Adam Libuša Adam Libuša 2,077 2 2 gold badges 11 11 silver badges 14 14 bronze badges Possible duplicate of Why is Clean Code suggesting avoiding protected variables? Commented Mar 11, 2016 at 9:21

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.

Commented Mar 11, 2016 at 9:51 Derived classes are part of the outer world. Commented Mar 11, 2016 at 10:40

Don't forget that protected doesn't always mean access is locked to the inheritance hierarchy. In Java, it grants package level access also.

Commented Mar 11, 2016 at 11:49

My professor used to say that "There are things I wouldn't tell my children. Those I my private fields."

Commented Mar 11, 2016 at 18:52

17 Answers 17

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.

answered Mar 11, 2016 at 9:30 27.7k 15 15 gold badges 83 83 silver badges 87 87 bronze badges

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.

Commented Mar 11, 2016 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".

Commented Mar 13, 2016 at 19:02

@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.

Commented Mar 13, 2016 at 19:11

""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.

Commented Mar 14, 2016 at 4:34 I'd toss you more than +1 if I could => That's what we call bounty @abluejelly Commented Mar 18, 2016 at 9:51

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.

103 5 5 bronze badges answered Mar 11, 2016 at 9:34 Sebastian Redl Sebastian Redl 15.4k 7 7 gold badges 59 59 silver badges 53 53 bronze badges +1 for the theoretical scenario of "affected by an infinite amount of code" Commented Mar 11, 2016 at 13:53

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.

Commented Mar 11, 2016 at 15:05 Or put simply: protected is for methods, not for data members. Commented Mar 11, 2016 at 15:35

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.

Commented Mar 11, 2016 at 16:05

@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.

Commented Mar 14, 2016 at 7:51

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.

answered Mar 11, 2016 at 9:44 Robbie Dee Robbie Dee 9,815 2 2 gold badges 24 24 silver badges 53 53 bronze badges +1 for "ride a coach and horses through" anything. It's a great phrase that I wish I heard more. Commented Mar 11, 2016 at 19:38

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.

Commented Mar 12, 2016 at 10:05

@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).

Commented Mar 14, 2016 at 9:06

@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 :)

Commented Mar 14, 2016 at 9:09 @Luaan +1 for when it's okay to touch others' privates! Commented Mar 14, 2016 at 14:30

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.