What are the purposes of having private/protected members of a class/structure in object-oriented programming? What's the harm in having all members be public?
相关问题
- how to define constructor for Python's new Nam
- Keeping track of variable instances
- What uses more memory in c++? An 2 ints or 2 funct
- Object.create() bug?
- How Does WebSphere Choose the Classloading Order i
相关文章
- 接口B继承接口A,但是又不添加新的方法。这样有什么意义吗?
- Should client-server code be written in one “proje
- Algorithm for maximizing coverage of rectangular a
- Private static variables in php class
- NameError: name 'self' is not defined, eve
- Is there an existing solution for these particular
- Implementation Strategies for Object Orientation
- .NET - how to make a class such that only one othe
Encapsulation. I.e. hiding the implementation of your class data. This allows you to change it later, without breaking all client code. E.g. if you have
your clients may write code like
now if you realize that
foo
should actually be a double rather than int, you change it:and the client code fails to compile :-(
With a well designed interface, the change of the internals (private parts) may even include turning a member variable into a calculation or vice versa:
(using String properties for the sake of simplicity - in a real world design some of these would probably deserve to have their own type.)
With this design, you are free to e.g. introduce an
Address
property internally, which would contain street address, zip code and country code, and rewrite your accessors to use the fields of this private member instead, without your clients noticing anything.You could also decide freely whether to calculate the hash code every time, or to cache it into a private variable in order to improve performance. If that cache field was public, however, anyone could change it, which could ruin hash map behaviour and introduce subtle bugs. So encapsulation is key in guaranteeing the consistency of the your object's internal state. E.g. in the above example, your setters can easily validate the zip code and country code, to prevent setting invalid values. You can even ensure that the zip code format is valid for the actual country, that is, ensure a validity criteria spanning multiple properties. With a well designed interface, you can enforce this binding by e.g. providing only a setter to set both properties at the same time:
However, with public fields you simply don't have these choices.
A special use case for private fields is immutable objects; this is very common in e.g. Java, examples are
String
andBigDecimal
. These classes have no public setters at all, which guarantees that their objects, once created, will not change their state. This enables a lot of performance optimizations, as well as makes them easier to use in e.g. multithreaded programs, ORM etc.No harm at all depending on the audience and consumption of the class. Let me repeat that one more time so it sinks in.
No harm at all depending on the audience and consumption of the class.
For many small projects of one or two people that take a month or so, getting all of the private and public definitions down perfectly might increase the work load substantially. On large, projects, however, where there may be multiple teams and teams are not geographically located together, getting the correct design of all of the public interfaces down at the start can greatly increase the likely hood of success of the project overall.
So you really have to look at how a class is going to be consumed and by whom before you can even begin to answer this question. Likewise, how long is the software development life-cycle going to be? Is it months? Years? Decades? Are there going to be other people besides you using the class?
The more "public" the class (ie the more people that will be consuming and using the class) the more important it is to nail down a solid public interface and stick to it.
A short example: You may need to ensure certain conditions on that value. In this case, setting it directly may break such a condition.
Many people argument like "you may not want everybody to read it", but I think the constraint of setting a value is a more usable example.
You may want to read the Information Hiding topic on wikipedia.
Essentially, private members allow a class to hide its implementation details from external consumers. This allows a class to better control how it data and behavior will be expressed, and allows the consumer to be ignorant of details that are not relevant to the primary purpose of the class.
Hiding implementation details improves the maintainability of a program by preventing code external from the class from establishing dependencies on those details. This allows the implementation to change independent of external consumers - with a reduced risk of breaking existing behavior. When private implementation details become public, they cannot be changed without the possibility of breaking consumers of the class that depend on those details.
Private members also allow a class to protect it's implementation from external abuse. Typically, the state of a class has internal dependencies which define when the state is valid - and when it is not. We can consider the rules that govern the validity of state information to be invariant - meaning that the class always expects them to be true. Exposing private details, allows external code to modify this state in a way that may violate the invariants, and therefore compromise the validity (and behavior) of the class.
An additional benefit of information hiding, is that it reduces the surface area that consumers of the class have to understand in order to properly interact with the class. Simplification is generally a good thing. It allows consumers to focus on understanding the public interface, and not how the class achieves its functionality.
It really depends on your ideology. The idea is to hide information that shouldn't be exposed for some reason.
If you have a library you wish to publish online, lots of people will download it and some may use it in their code. If you keep your public API to a minimum and hide the implementation details, you'll have less of a hard time updating it when you encounter bugs or want to improve the code.
Also, in Java, for example, you have no way to restrict access to a member variable without changing its visibility, so you often find yourself prematurely creating getters and setters and making the variable itself private or protected. In Python, for example, that problem doesn't exist because you can make getters and setters behave like variables for direct access (they're called properties there).
Lastly, sometimes you need to have methods which require a consistent state to be useful and would lead to problems if accessed directly.
A rule of thumb is: if you expose something, someone will use it. And most often they'll use it for the wrong reasons (i.e. not how you intended them to be used). In this case Information Hiding is the equivalent of child locks on weapon cabinets.
To add to Peter's answer, say your class stores a name, and you want to change it from using a single name string to a first name string and a surname string. If your members were public, other classes might read (or write) the name variable directly, and would break when that variable disappeared.
Not to mention that you might not want other classes to have the ability to edit your members at all.