类中私有成员的用途
在面向对象编程中,类/结构的私有/受保护成员的目的是什么?让所有成员公开有什么坏处?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
封装。即隐藏类数据的实现。这允许您稍后更改它,而不会破坏所有客户端代码。例如,如果您
的客户可能会像现在这样编写代码,
如果您意识到
foo
实际上应该是 double 而不是 int,那么您会更改它:客户端代码无法编译:-(
并且 接口,内部(私有部分)的更改甚至可能包括将成员变量转换为计算,反之亦然:(
为了简单起见,使用 String 属性 - 在现实世界的设计中,其中一些可能应该拥有自己的属性类型。)
通过这种设计,您可以自由地在内部引入一个
Address
属性,其中包含街道地址、邮政编码和国家/地区代码,并重写您的访问器以使用此私有成员的字段,而您的客户不会注意到任何事情,您还可以自由决定是否每次都计算哈希码,或者将其缓存到私有变量中以提高性能,但是,如果该缓存字段是公共的,则任何人都可以更改它。可能会破坏哈希映射行为并引入微妙的错误。因此,封装是保证对象内部状态一致性的关键。例如,在上面的示例中,您的设置者可以轻松验证邮政编码和国家/地区代码,以防止设置无效值。您甚至可以确保邮政编码格式对于实际国家/地区有效,即确保跨越多个属性的有效性标准。通过精心设计的界面,您可以通过例如仅提供一个 setter 来同时设置两个属性来强制执行此绑定:
但是,对于公共字段,您根本没有这些选择。
私有字段的一个特殊用例是不可变对象;这在 Java 等中很常见,例如
String
和BigDecimal
。这些类根本没有公共设置器,这保证了它们的对象一旦创建就不会改变它们的状态。这可以实现大量性能优化,并使其更易于在多线程程序、ORM 等中使用。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.您可能想阅读维基百科上的信息隐藏主题。
本质上,私有成员允许类向外部消费者隐藏其实现细节。这允许类更好地控制其数据和行为的表达方式,并允许消费者不知道与课程的主要目的无关。
隐藏实现细节可以防止类外部的代码建立对这些细节的依赖关系,从而提高程序的可维护性。这使得实现能够独立于外部消费者而改变——同时降低破坏现有行为的风险。当私有实现细节公开时,如果不破坏依赖于这些细节的类的使用者,就无法更改它们。
私有成员还允许类保护其实现免受外部滥用。通常,类的状态具有内部依赖关系,这些依赖关系定义状态何时有效以及何时无效。我们可以认为控制状态信息有效性的规则是不变的 - 这意味着该类始终期望它们为真。暴露私有细节,允许外部代码以可能违反不变量的方式修改此状态,从而损害类的有效性(和行为)。
信息隐藏的另一个好处是,它减少了类的使用者为了与类正确交互而必须理解的表面积。简化通常是一件好事。它允许消费者专注于理解公共接口,而不是类如何实现其功能。
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.
此 第 7.4 节:保护您的隐私部分中有很好的解释="http://www.intap.net/%7Edrw/cpp/index.htm" rel="nofollow noreferrer">在线 C++ 教程。
上面的解释解释了使用
private
如何简化学习曲线。下面是一个解释“代码破坏”方面的示例:这是一个类
ParameterIO
,它读取和写入整数参数向量以下代码破坏了该类:
Nicely explained in Section 7.4: Protect your Private Parts of this online C++ tutorial.
The above explanation explains how using
private
eases the learning curve. Here's an example which explains the "code breaking" aspect:Here's a class
ParameterIO
which reads and writes a vector of integer parametersThe following code breaks this class:
打个比方,将私人成员暴露为公众就像在汽车仪表板上有一个选项,可以让您调整发动机油压。
汽车应该在内部(私下)管理它,并且应该防止用户直接弄乱它(
Metaphorically, exposing private members as public is like having an option on your car's dashboard that allows you to tweak the engine oil pressure.
The car should manage that internally (privately), and the user should be shielded from messing with it directly (encapsulation), for obvious reasons.
这实际上取决于你的意识形态。这个想法是隐藏由于某种原因不应公开的信息。
如果您有一个想要在线发布的库,很多人都会下载它,有些人可能会在他们的代码中使用它。如果您将公共 API 保持在最低限度并隐藏实现细节,那么当您遇到错误或想要改进代码时,更新它就不会那么困难。
另外,例如,在 Java 中,您无法在不更改成员变量可见性的情况下限制对成员变量的访问,因此您经常会发现自己过早地创建了 getter 和 setter,并将变量本身设置为私有或受保护。例如,在 Python 中,这个问题就不存在,因为您可以使 getter 和 setter 的行为类似于直接访问的变量(在那里它们被称为属性)。
最后,有时您需要拥有需要一致状态的方法才能发挥作用,但如果直接访问则会导致问题。
经验法则是:如果你公开某些东西,就会有人使用它。大多数情况下,他们会出于错误的原因使用它(即不是您想要的使用方式)。在这种情况下,信息隐藏相当于武器柜上的儿童锁。
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.
要添加到 Peter 的答案中,假设您的类存储了一个名称,并且您希望将其从使用单个名称字符串更改为使用名字字符串和姓氏字符串。如果您的成员是公共的,其他类可能会直接读取(或写入)名称变量,并且当该变量消失时会中断。
更不用说您可能根本不希望其他类能够编辑您的成员。
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.
有时您不想向所有人透露私人信息。例如,您不想让公众知道您的年龄,但您可能想告诉人们您是否已超过 25 岁。
Sometime you don't want to reveal private information to everybody. E.g you don't want to let your age be known to public but you may want tell people if you are above 25.
人体拥有内脏器官的目的是什么?把所有器官都放在外面有什么坏处?
确切地!
简短的答案是:因为你需要它们,所以你不能没有它们,你不能将它们暴露给每个人来修改和使用它们,因为这可能会杀了你(导致你的类无法正常运行)。
What are the purposes of having inner organs in the human body? What's the harm in having all organs outside?
Exactly!
The short answer would be: Because you need them so you can't live without them and you can't expose them to everyone to modify and play around with them because that could kill you (cause your class not to function properly).
完全没有坏处,具体取决于班级的观众和消费。让我再重复一遍,以便大家理解。
没有什么坏处,具体取决于课堂的观众和消费。
对于许多一两个人需要一个月左右的小项目来说,完美地记录所有私人和公共定义可能会大大增加工作量。然而,在大型项目中,可能有多个团队,并且团队在地理位置上并不在一起,从一开始就正确设计所有公共接口可以大大增加项目整体成功的可能性。
因此,在开始回答这个问题之前,您确实必须先了解一堂课将如何使用以及由谁使用。同样,软件开发生命周期有多长?是几个月吗?年?几十年?除了你之外还会有其他人使用该课程吗?
类越“公共”(即消费和使用该类的人越多),确定一个可靠的公共接口并坚持下去就越重要。
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.