对私人与公共的务实看法
我一直对 public
、protected
和 private
属性这个主题感到好奇。我的记忆很容易回想起我不得不破解某人的代码的时候,并且将被破解的类变量声明为private
总是令人心烦意乱。
另外,有(更多)次我自己写过一门课,但从未认识到将财产私有化有任何潜在收益。我应该在这里指出,使用公共变量不是我的习惯:我通过使用 getter 和 setter 来遵守 OOP 原则。
那么,这些限制的全部意义是什么?
I've always wondered on the topic of public
, protected
and private
properties. My memory can easily recall times when I had to hack somebody's code, and having the hacked-upon class variables declared as private
was always upsetting.
Also, there were (more) times I've written a class myself, and had never recognized any potential gain of privatizing the property. I should note here that using public vars is not in my habit: I adhere to the principles of OOP by utilizing getters and setters.
So, what's the whole point in these restrictions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
private和public的使用称为封装。这是一个简单的见解:软件包(类或模块)需要内部和外部。
外部(公众)是你与世界其他地方的契约。你应该尽量保持简单、连贯、明显、万无一失,而且非常重要的是稳定。
如果您对优秀的软件设计感兴趣,那么规则很简单:将所有数据设为私有,并仅在需要时将方法公开。
隐藏数据的原则是类中所有字段的总和定义对象状态。对于一个编写良好的类,每个对象都应该负责保持有效的状态。如果国家的一部分是公共的,阶级就永远无法提供这样的保证。
举一个小例子,假设我们有:
您无法阻止该类的用户忽略 AdvanceDays() 并简单地执行以下操作:
但是如果您将 y, m, d 设为私有并测试所有 MyDate 方法,您可以保证系统中只有有效日期。
The use of private and public is called Encapsulation. It is the simple insight that a software package (class or module) needs an inside and an outside.
The outside (public) is your contract with the rest of the world. You should try to keep it simple, coherent, obvious, foolproof and, very important, stable.
If you are interested in good software design the rule simply is: make all data private, and make methods only public when they need to be.
The principle for hiding the data is that the sum of all fields in a class define the objects state. For a well written class, each object should be responsible for keeping a valid state. If part of the state is public, the class can never give such guarantees.
A small example, suppose we have:
You cannot prevent a user of the class to ignore AdvanceDays() and simply do:
But if you make
y, m, d
private and test all your MyDate methods, you can guarantee that there will only be valid dates in the system.重点是使用
private
和protected
来防止暴露类的内部细节,以便其他类只能访问您的类提供的公共“接口”。如果做得正确的话,这是值得的。我同意
private
可能是一个真正的痛苦,特别是如果您从库中扩展类。不久前,我不得不从 Piccolo.NET 框架扩展各种类,它是令人耳目一新的是,他们已将我需要的所有内容声明为protected
而不是private
,因此我能够扩展我需要的所有内容,而无需复制他们的代码和/或修改库。从中得到的一个重要教训是,如果您正在为库或其他“可重用”组件编写代码,那么在声明任何私有
之前,您确实应该三思而后行。The whole point is to use
private
andprotected
to prevent exposing internal details of your class, so that other classes only have access to the public "interfaces" provided by your class. This can be worthwhile if done properly.I agree that
private
can be a real pain, especially if you are extending classes from a library. Awhile back I had to extend various classes from the Piccolo.NET framework and it was refreshing that they had declared everything I needed asprotected
instead ofprivate
, so I was able to extend everything I needed without having to copy their code and/or modify the library. An important take-away lesson from that is if you are writing code for a library or other "re-usable" component, that you really should think twice before declaring anythingprivate
.关键字 private 不应该用于私有化您想要公开的属性,而应该用于保护类的内部代码。我发现它们非常有用,因为它们可以帮助您定义必须对每个人都可以访问的代码隐藏的部分。
The keyword private shouldn't be used to privatize a property that you want to expose, but to protect the internal code of your class. I found them very helpful because they help you to define the portions of your code that must be hidden from those that can be accessible to everyone.
我想到的一个例子是,当您需要在设置/获取私人成员的值之前进行某种调整或检查时。因此,您需要创建一个具有某些逻辑的公共 setter/getter(检查某些内容是否为 null 或任何其他计算),而不是直接访问私有变量并且始终必须在代码中处理该逻辑。它有助于代码合同和预期。
另一个例子是辅助函数。您可能会将一些较大的逻辑分解为较小的函数,但这并不意味着您希望每个人都看到并使用这些辅助函数,您只希望它们访问您的主要 API 函数。
换句话说,您希望从界面中隐藏代码中的一些内部内容。
请观看一些有关 API 的视频,例如此 Google 演讲。
One example that comes to my mind is when you need to do some sort of adjustment or checking before setting/getting the value of a private member. Therefore you'd create a public setter/getter with some logic (check if something is null or any other calculations) instead of accessing the private variable directly and always having to handle that logic in your code. It helps with code contracts and what is expected.
Another example is helper functions. You might break down some of your bigger logic into smaller functions, but that doesn't mean you want to everyone to see and use these helper functions, you only want them to access your main API functions.
In other words, you want to hide some of the internals in your code from the interface.
See some videos on APIs, such as this Google talk.
最近,我非常荣幸地能够从头开始设计和实现一个对象系统,因此我采取了强制所有变量(相当于)
受保护
的策略。我的目标是鼓励用户始终将变量视为实现的一部分,而不是规范的一部分。 OTOH,我还留下了一些钩子,以允许代码打破此限制,因为仍然有理由不遵循它(例如,对象序列化引擎无法遵循规则)。请注意,我的类不需要强制执行安全性;该语言还有其他机制。
Having recently had the extreme luxury of being able to design and implement an object system from scratch, I took the policy of forcing all variables to be (equivalent to)
protected
. My goal was to encourage users to always treat the variables as part of the implementation and not the specification. OTOH, I also left in hooks to allow code to break this restriction as there remain reasons to not follow it (e.g., the object serialization engine cannot follow the rules).Note that my classes did not need to enforce security; the language had other mechanisms for that.
在我看来,使用私有成员的最重要原因是隐藏实现,以便将来可以更改而无需更改后代。
In my opinion the most important reason for use private members is hiding implementation, so that it can changed in the future without changing descendants.
有些语言(例如 Smalltalk)根本没有可见性修饰符。
在 Smalltalk 的情况下,所有实例变量始终是私有的,所有方法始终是公共的。开发人员通过将方法放入“私有”协议中来表明该方法是“私有”的(可能会更改的东西,或者本身没有多大意义的辅助方法)。
然后,类的用户可以看到,他们在向该类发送标记为私有的消息时应该三思而后行,但仍然可以自由地使用该方法。
(注意:Smalltalk 中的“属性”只是 getter 和 setter 方法。)
Some languages - Smalltalk, for instance - don't have visibility modifiers at all.
In Smalltalk's case, all instance variables are always private and all methods are always public. A developer indicates that a method's "private" - something that might change, or a helper method that doesn't make much sense on its own - by putting the method in the "private" protocol.
Users of a class can then see that they should think twice about sending a message marked private to that class, but still have the freedom to make use of the method.
(Note: "properties" in Smalltalk are simply getter and setter methods.)
我个人很少使用受保护的成员。我通常喜欢组合,即装饰器模式或策略模式。在极少数情况下,我相信子类(程序员)能够正确处理受保护的变量。有时我有受保护的方法来显式地提供专门为子类提供的接口,但这种情况实际上很少见。
大多数时候,我有一个仅包含公共纯虚函数的抽象基类(现在谈论 C++),并且实现类实现了这些。有时他们会添加一些特殊的初始化方法或其他特定功能,但其余的都是私有的。
I personally rarely make use of protected members. I usually favor composition, the decorator pattern or the strategy pattern. There are very few cases in which I trust a subclass(ing programmer) to handle protected variables correctly. Sometimes I have protected methods to explicitly offer an interface specifically for subclasses, but these cases are actually rare.
Most of the time I have an absract base class with only public pure virtuals (talking C++ now), and implementing classes implement these. Sometimes they add some special initialization methods or other specific features, but the rest is private.
首先,“属性”在不同的语言中可能指代不同的事物。例如,在 Java 中,您指的是实例变量,而 C# 则两者之间有区别。
我假设你指的是实例变量,因为你提到了 getters/setters。
正如其他人提到的原因是封装。封装给我们带来了什么?
灵活性
当事情必须改变时(而且通常如此),我们不太可能通过正确封装属性来破坏构建。
例如,我们可能决定进行如下更改:
如果我们一开始就没有封装“foo”,那么我们将有更多的代码需要更改。 (比这一行)
封装属性的另一个原因是提供一种防弹代码的方法:
这也很方便,因为我们可以在变异器中设置断点,这样每当有东西试图修改我们的代码时我们就可以中断数据。
如果我们的财产是公共的,那么我们就不能这样做!
First of all 'properties' could refer to different things in different languages. For example, in Java you would be meaning instance variables, whilst C# has a distinction between the two.
I'm going to assume you mean instance variables since you mention getters/setters.
The reason as others have mentioned is Encapsulation. And what does Encapsulation buy us?
Flexibility
When things have to change (and they usually do), we are much less likely to break the build by properly encapsulating properties.
For example we may decide to make a change like:
If we had not encapsulated 'foo' to begin with, then we'd have much more code to change. (than this one line)
Another reason to encapsulate a property, is to provide a way of bullet-proofing our code:
This is also handy as we can set a breakpoint in the mutator, so that we can break whenever something tries to modify our data.
If our property was public, then we could not do any of this!