ChatGPT解决这个技术问题 Extra ChatGPT

Private vs Protected - Visibility Good-Practice Concern [closed]

Closed. This question is opinion-based. It is not currently accepting answers. Want to improve this question? Update the question so it can be answered with facts and citations by editing this post. Closed 4 years ago. Improve this question

I've been searching and I know the theoretic difference.

public - Any class/function may access the method/property.

protected - Only this class and any subclasses may access the method/property.

private - Only this class may access the method/property. It won't even be inherited.

That's all fine and well, the question is, what's the practical difference between them? When would you use private and when would you use protected? Is there a standard or acceptable good practice over this one?

Up until now, to retain the concept of inheritance and polymorphism, I use public for anything that should be accessed from the outside (like constructors and main class functionality), and protected for internal methods (logic, helper methods etc). Am I on the right track?

(Note that this question is for me, but also for future reference as I haven't seen a question like this one SO).

Does it matter? Any language with OOP support has this concern. I happen to program in PHP, but I think the question applies for any OOP supporting language.
Okay fair enough, just wondering if you had forgotten to tag. Now I see the oop tag.
I have to set the visibility (private/public/protected) for each and every property of the class? Or only some of them need to have a visibility type? If yes, how to decide which property need to have a visibility set in top of class?
offhand, the difference between protected and private seems obvious. Use protected if subclasses will use the method/variable, otherwise use private. Specifically, if subclasses would have to re-define a very similar private variable in the parent, just make it protected.
There is another access specifier internal in C# language which restricts the access level of a class or its members within a physical assembly. Though, I'm not sure about its support or something similar in other languages.

J
JB Nizet

No, you're not on the right track. A good rule of thumb is: make everything as private as possible. This makes your class more encapsulated, and allows for changing the internals of the class without affecting the code using your class.

If you design your class to be inheritable, then carefully choose what may be overridden and accessible from subclasses, and make that protected (and final, talking of Java, if you want to make it accessible but not overridable). But be aware that, as soon as you accept to have subclasses of your class, and there is a protected field or method, this field or method is part of the public API of the class, and may not be changed later without breaking subclasses.

A class that is not intended to be inherited should be made final (in Java). You might relax some access rules (private to protected, final to non-final) for the sake of unit-testing, but then document it, and make it clear that although the method is protected, it's not supposed to be overridden.


The real question here, is about private vs protected When do I want a property to be inherited, and when don't I? I can't really tell if a user sometimes in the future wants to take my class and extend it...
Well, the question is not what the user wants to override, the question is what you want to allow to be overridden. Usually it helps to switch sides and try to think: If I used that class and created a subclass, what would I want to be able to override? Sometimes other users will still miss things...
Protected fields are bad practice in inheritance!. Please beware of it. Here is why
Private fields are bad in practice in inheritance!. (over exaggerating) Please read my answer.
Typical control-freak opinion.
C
Community

Let me preface this by saying I'm talking primarily about method access here, and to a slightly lesser extent, marking classes final, not member access.

The old wisdom

"mark it private unless you have a good reason not to"

made sense in days when it was written, before open source dominated the developer library space and VCS/dependency mgmt. became hyper collaborative thanks to Github, Maven, etc. Back then there was also money to be made by constraining the way(s) in which a library could be utilized. I spent probably the first 8 or 9 years of my career strictly adhering to this "best practice".

Today, I believe it to be bad advice. Sometimes there's a reasonable argument to mark a method private, or a class final but it's exceedingly rare, and even then it's probably not improving anything.

Have you ever:

Been disappointed, surprised or hurt by a library etc. that had a bug that could have been fixed with inheritance and few lines of code, but due to private / final methods and classes were forced to wait for an official patch that might never come? I have.

Wanted to use a library for a slightly different use case than was imagined by the authors but were unable to do so because of private / final methods and classes? I have.

Been disappointed, surprised or hurt by a library etc. that was overly permissive in it's extensibility? I have not.

These are the three biggest rationalizations I've heard for marking methods private by default:

Rationalization #1: It's unsafe and there's no reason to override a specific method

I can't count the number of times I've been wrong about whether or not there will ever be a need to override a specific method I've written. Having worked on several popular open source libs, I learned the hard way the true cost of marking things private. It often eliminates the only practical solution to unforseen problems or use cases. Conversely, I've never in 16+ years of professional development regretted marking a method protected instead of private for reasons related to API safety. When a developer chooses to extend a class and override a method, they are consciously saying "I know what I'm doing." and for the sake of productivity that should be enough. period. If it's dangerous, note it in the class/method Javadocs, don't just blindly slam the door shut.

Marking methods protected by default is a mitigation for one of the major issues in modern SW development: failure of imagination.

Rationalization #2: It keeps the public API / Javadocs clean

This one is more reasonable, and depending on the target audience it might even be the right thing to do, but it's worth considering what the cost of keeping the API "clean" actually is: extensibility. For the reasons mentioned above, it probably makes more sense to mark things protected by default just in case.

Rationalization #3: My software is commercial and I need to restrict it's use.

This is reasonable too, but as a consumer I'd go with the less restrictive competitor (assuming no significant quality differences exist) every time.

Never say never

I'm not saying never mark methods private. I'm saying the better rule of thumb is to "make methods protected unless there's a good reason not to".

This advice is best suited for those working on libraries or larger scale projects that have been broken into modules. For smaller or more monolithic projects it doesn't tend to matter as much since you control all the code anyway and it's easy to change the access level of your code if/when you need it. Even then though, I'd still give the same advice :-)


W.r.t. your Rationalization # 1 - When I mark something as protected I choose to do that explicitly as I feel that this behavior isn't final and might be a case where my child classes would want to override it. If I'm not so sure then I would want to make it private by default. Specially in a language like C# which keeps a method non-virtual by default, adding just protected access specifier makes no sense.You have to add both virtual and protected keywords to make your intent very clear. Also, people prefer association over inheritance so protected as default is difficult to perceive
The combination of keywords necessary to make a method overridable is a language detail IMHO. The counter argument I present to rationalization #1 is squarely aimed at the case you mention "If I'm not so sure...". Practically speaking, if you can't think of a reason why it would be dangerous then theres more to be gained by opting for extensibility. When you say 'association' I'm taking that to be a synonym for composition, in which case I don't see it mattering either way.
I don't remember how many times I had to "clone" the underlying classes just because I wanted to override 1 or 2 or the methods. And like what you said, with the social trend that we're sharing more code than ever before, it makes much more sense to go with protected than private by default. i.e. be more open to your own logics.
Agree. I just wanted to tweak Java's BufferedReader to handle custom line delimiters. Thanks to private fields I have to clone the entire class rather than simply extending it and overriding readLine().
L
Larry

Stop abusing private fields!!!

The comments here seem to be overwhelmingly supportive towards using private fields. Well, then I have something different to say.

Are private fields good in principle? Yes. But saying that a golden rule is make everything private when you're not sure is definitely wrong! You won't see the problem until you run into one. In my opinion, you should mark fields as protected if you're not sure.

There are two cases you want to extend a class:

You want to add extra functionality to a base class

You want to modify existing class that's outside the current package (in some libraries perhaps)

There's nothing wrong with private fields in the first case. The fact that people are abusing private fields makes it so frustrating when you find out you can't modify shit.

Consider a simple library that models cars:

class Car {
    private screw;
    public assembleCar() {
       screw.install();
    };
    private putScrewsTogether() {
       ...
    };
}

The library author thought: there's no reason the users of my library need to access the implementation detail of assembleCar() right? Let's mark screw as private.

Well, the author is wrong. If you want to modify only the assembleCar() method without copying the whole class into your package, you're out of luck. You have to rewrite your own screw field. Let's say this car uses a dozen of screws, and each of them involves some untrivial initialization code in different private methods, and these screws are all marked private. At this point, it starts to suck.

Yes, you can argue with me that well the library author could have written better code so there's nothing wrong with private fields. I'm not arguing that private field is a problem with OOP. It is a problem when people are using them.

The moral of the story is, if you're writing a library, you never know if your users want to access a particular field. If you're unsure, mark it protected so everyone would be happier later. At least don't abuse private field.

I very much support Nick's answer.


Using private fields is mostly saying that inheritance is the wrong abstraction to alter a certain behavior of a class/object (if used consciously). Altering will usually silently violate LSP as behavior is changed without the API changing. Great answer, +1.
Preach! Private is the bane of my existence when trying to write Minecraft mods. Nothing more annoying than having to use Reflection or ASM to fix that.
As I understood Nick's answer he was referring mostly to methods not properties. I totally agree we shouldn't declare methods private every time and usage of those needs to be thoughtful, but cmon why would you advise to declare properties protected over private just because youd want to easier "rewrite" the class. Totally share your frustration as I'm working with 3rd p's daily, but let's encourage people to create solid architecture and not just saying "the code would end up being crap so let's have protected from the beginning so we can easily rewrite it". Although I share your frustration.
A
Anurag

I read an article a while ago that talked about locking down every class as much as possible. Make everything final and private unless you have an immediate need to expose some data or functionality to the outside world. It's always easy to expand the scope to be more permissible later on, but not the other way around. First consider making as many things as possible final which will make choosing between private and protected much easier.

Make all classes final unless you need to subclass them right away. Make all methods final unless you need to subclass and override them right away. Make all method parameters final unless you need to change them within the body of the method, which is kinda awkward most of the times anyways.

Now if you're left with a final class, then make everything private unless something is absolutely needed by the world - make that public.

If you're left with a class that does have subclass(es), then carefully examine every property and method. First consider if you even want to expose that property/method to subclasses. If you do, then consider whether a subclass can wreak havoc on your object if it messed up the property value or method implementation in the process of overriding. If it's possible, and you want to protect your class' property/method even from subclasses (sounds ironic, I know), then make it private. Otherwise make it protected.

Disclaimer: I don't program much in Java :)


To clarify: A final class in Java is a class which cannot be inherited from. A final method is non-virtual, i.e. not overridable by a subclass (Java methods are virtual by default). A final field/parameter/variable is an immutable variable reference (in the sense that it cannot be modified after it was initialized).
Funnily enough, I've seen the exact opposite advice, that nothing should be final unless it is certain that overriding the thing in question has the potential to break an invariant. That way anybody is free to extend your classes as needed.
Can you name one case in your programming career where marking a method parameter "final" made a difference to your understanding? (other than if required by the compiler)
A
Alok Save

When would you use private and when would you use protected?

Private Inheritance can be thought of Implemented in terms of relationship rather than a IS-A relationship. Simply put, the external interface of the inheriting class has no (visible) relationship to the inherited class, It uses the private inheritance only to implement a similar functionality which the Base class provides.

Unlike, Private Inheritance, Protected inheritance is a restricted form of Inheritance,wherein the deriving class IS-A kind of the Base class and it wants to restrict the access of the derived members only to the derived class.


That "Implemented in terms of relationship" is a HAS-A relationship. If all attributes are private, the only way to access them is thru methods. This is the same thing as if the sub-class contained an object of the super-class. Eliminating all protected attributes from your concrete classes means eliminating all inheritance from them too.
Interesting thought process - Private Inheritance. @shawnhcorey thanks for making it explicit that it is pointing towards HAS-A relationship aka association (which can be aggregation or composition). I feel this post should also be updated to clarify the same.
u
ujwal dhakal

Well it is all about encapsulation if the paybill classes handles billing of payment then in product class why would it needs the whole process of billing process i.e payment method how to pay where to pay .. so only letting what are used for other classes and objects nothing more than that public for those where other classes would use too, protected for those limit only for extending classes. As you are madara uchiha the private is like "limboo" you can see it (you class only single class).