公共和私有访问修饰符
如果我们可以通过 setter 和 getter 访问 private 成员,那么 private 有什么用呢?
if we can access the private members through setters and getters then what is the use of private?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要私有来强制封装。将某些东西的实现与接口分开是面向对象编程的基本范例之一。这减少了不同程序部分之间的耦合,从长远来看使其更易于维护。
以下面的例子为例:
如果您将上面的代码更改为简单地将 someThing 公开,那么您的代码肯定会减少,但是如果有一天该 someThing 需要更改为更复杂的对象以实现某些新功能,而旧代码仍然可以很好地处理字符串那么你需要改变一切。通过隔离某些事物的内部表示,您可以更轻松地发展您的系统
还有其他原因使封装成为一件好事(tm),这只是一个愚蠢的例子来说明这一点。
编辑
现在对于使用受保护还是私有或使用类似于某些语言(Delphi、C#)中的属性的概念而不是 getter 和 setter(如 Java 中)存在一些争论。
受保护的而不是私有的将允许代码的客户端更容易地进行更改,但它确实更多地暴露了系统的内部结构,因此需要在 API 的可用性和可维护性之间寻求平衡。然而,封装的基本原则仍然存在。
无论选择哪种选项,仍然需要公开一致且处于同一抽象级别的功能,并隐藏如何完成此操作的血淋淋的细节。
对我来说,争论并不是要宣布对私有的圣战,而是要找到一种方法来提供可扩展性和灵活性,同时又不破坏 API 的一致性。
这里 一些< /a> 有趣如果您想进一步挖掘,请阅读有关 private 的内容。但是我必须强调,在对私有形成看法之前,您应该真正掌握封装的概念 和多态性,它们表面上的简单性确实隐藏了一些微妙的复杂性。
You need the private to enforce Encapsulation. It is one of the fundamental paradigm of Object Oriented programming to keep the implementation of something separate from the interface. This reduces the coupling between your different program parts and in the long run make it more maintainable.
Take the following example :
If you change above to simply put someThing public, sure you have less code, but if one day that someThing needs to change to a more complex object for some new functionality while the old code could still work fine with a string then you need to change everything. By isolating the internal representation of someThing you can evolve your system much more easily
There are other reasons that makes encapsulation a Good Thing (tm), this is just a silly example to illustrate the point.
EDIT
There is somewhat of a debate right now as to using protected vs private or to use concepts akin to properties in some languages (Delphi, C#) rather than getters and setters (as in Java).
Protected rather than private will allow easier changes by the clients of the code but it does expose the innards of your system more so there is a balance to strive for between usability of the API and it's maintainability. However the basic principle of encapsulation remains.
Whatever the option chosen one still needs to expose functionality that is coherent and on the same level of abstraction and hide the gory details of how this is done.
To me the debate is not to declare a jihad against private but to find a way to provide extensibility and flexibility while not breaking the coherence of the API.
Here some interesting reading about private if you want to dig further. However I must stress that before forming an opinion about private you should really master the concepts of encapsulation and polymorphism, their apparent simplicity does hides some subtle complexities.
因为 getter 和 setter 可以充当代理。他们这样做是为了隐藏类的实际内部,只让外部类通过方法访问数据。让你可以随心所欲地对待班级的内部。
仅仅因为您的 getter/setter 名为
getName()
并且您的属性名为name
,并不意味着它永远都是这样。如果您想将变量更改为
fullName
,该怎么办?如果直接访问公共变量,这种更改会破坏很多代码。相反,您可以简单地重新映射getName()
检索数据的位置。我最好的例子之一是我自己的 URL 类,我允许在其中创建和操作 URL。如果要设置方案,可以获取
$obj->setScheme()
。但是,您不知道我是否在每次更改 URL 时手动创建字符串,是否将它们存储为单独的部分。这给了我灵活性,因为我可以随心所欲地存储您的数据。此外,我可以在存储数据之前对数据进行操作。在我的 URL 类中,我假设所有方案和主机名都是小写的。我可以通过将通过 setHost() 保存的所有字符串转换为小写,然后存储它们来标准化它。如果我使用公共变量,您必须假设放入数据的客户端正确存储了它。
他们还可以验证传入的信息以确保其是有效数据,如果不是则导致错误。
Because the getters and setters can act as a proxy. They make it so that you can hide the actual insides of the class, and only let the outside classes access the data through methods. Allowing you to treat the inners of the class however you want.
Just because your getter/setter is named
getName()
and your property is calledname
, doesn't mean it will always be that way.What if you wanted to change the variable to be
fullName
. If you directly accessed public variables, the change would break a lot of code. Instead, you can simply remap wheregetName()
retrieves its data from.One of my best examples of this is my own URL class, where I allow for creating and manipulating a URL. If you want to set the scheme, you can get
$obj->setScheme()
. However, you don't know whether I am manually making the string every time you change the URL, whether I am storing them as separate parts. This gives me flexibility as I can store your data however I want to.Furthermore, I can preform manipulations on the data before storing it. In my URL class, I assume that all schemes and host names are lowercase. I can standardize this by converting all strings saved via
setHost()
to lowercase, and then storing them. If I used a public variable, you would have to assume that the client that put the data in was correctly storing it.They can also validate information that is being passed in to make sure that it is valid data, and cause an error if it isn't.
没有人强迫您为每个变量添加 getter 和 setter。确实,盲目使用私有成员+虚拟吸气剂&每个变量的设置器都是毫无意义的,尽管许多“面向对象封装”教程出于某种原因一直这样做。一方面,从并发的角度来看,这种封装不是封装。
No one forces you to put in getters and setters for every variable. Indeed, blindly using private members + dummy getters & setters for every variable is pointless, even though many "object oriented encapsulation" tutorials do this all the time for some reason. For one thing, such encapsulation is no encapsulation from concurrency viewpoint.
我认为您真正想了解的是为什么我们使用带有私有支持字段的公共属性,而不是仅仅使用公共字段。 SO上有几个这样的问题;这是一个:
之间有什么区别C# 中的字段和属性?
I think what you really want to understand is why we use public properties with private backing fields, instead of just using public fields. There are several questions on SO like this; here's one:
What is the difference between a Field and a Property in C#?
我认为到目前为止你已经有了很好的答案(信息隐藏等等)。只是想添加有关使用设置器的建议。
正如您提到的,使用访问器使私有变量变得毫无意义,并且在某些环境中使用 getter 和 setter 的性能后果只会使其变得毫无价值。
另一方面,如果您没有这样的担忧,我认为使用 getter 并没有那么糟糕,但在使用 setter 之前您应该三思而后行。它们使您的对象可变,这在并发环境中尤其难以维护。
I think you have good answers so far (information hiding and all that). Just want to add a suggestion about using setters.
As you mentioned using accessors makes private variables a bit pointless and in some environments performance consequence of using getters and setters just makes it worthless.
On the other hand if you don't have such concerns, I think using getters isn't so bad, but you should think twice before using setters. They make your object mutable which is especially hard to maintain in concurrent environments.