我的问题是:为什么我们要这样做?为什么不能直接让一个类修改另一个类的全局变量?即使您不应该这样做,为什么还需要protected、private和public修饰符?好像程序员不相信自己不会这样做,尽管他们是编写程序的人。
提前感谢。
你说得对,这是因为我们不能相信自己。可变状态是计算机程序复杂性的主要因素,很容易构建一些一开始看起来还不错的东西,但随着系统变得越来越大,它就会失控。限制访问有助于减少对象状态以不可预测的方式改变的机会。这个想法是让对象通过定义良好的通道进行通信,而不是直接调整彼此的数据。这样我们就有希望测试单个对象,并对它们作为整个系统的一部分的行为有一些信心。
让我举个简单的例子(仅供示范):
class Foo {
void processBar() {
Bar bar = new Bar();
bar.value = 10;
bar.process();
}
}
class Bar {
public int value;
public void process() {
// Say some code
int compute = 10/value;
// Her you have to write some code to handle
// exception
}
}
一切看起来都很好,你感到高兴。但后来你意识到其他开发人员或者你使用的其他API将值设置为0
,导致在Bar.process()
函数中出现异常。
现在根据上述实现,你无法阻止用户将其设置为0。现在看下面的实现。
class Foo {
void processBar() {
Bar bar = new Bar();
bar.setValue(0);
bar.process();
}
}
class Bar {
public int value;
public void setValue(int value) {
if(value == 0)
throw new IllegalArgumentException("value = 0 is not allowed");
this.value = value;
}
public void process() {
// Say some code
int compute = 10/value;
// No need to write exception handling code
// so in theory can give u better performance too
}
}
现在不仅可以进行检查,还可以提供有用的异常信息,帮助快速发现错误并在早期解决。
这只是一个例子,面向对象编程的基础(封装、抽象等)可以帮助您标准化接口并隐藏底层实现。
例如,如果我有一个私有/受保护的实例变量,我可能有一个公共的“setter”方法来检查有效性、前提条件和执行其他活动——如果任何人都可以自由地直接修改实例变量,所有这些都将被绕过。
Java文档/教程中的另一个好处在于:http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html :
公共字段倾向于将您链接到特定的实现,并限制您更改代码的灵活性。
基本上有两个原因:
1)在Java中需要安全接口。例如,在您的计算机上运行Java小程序时,您希望确保该小程序无法访问未经授权的文件系统部分。如果没有可执行的安全性,小程序可以进入Java安全层并修改自己的权限。
2)即使每个人都是“可信任的”,有时候追求效率胜过常识,程序员会绕过API来访问内部接口,而不是增强API(尽管这通常比实际操作时间更长)。这会为稳定性和升级兼容性带来问题。
(在计算机古老的历史中,有一个传说,一种操作系统被应用程序员以这种方式处理,以至于维护操作系统的程序员被迫确保某些代码段(不是入口点,而是实际的内部代码序列)在操作系统修订时不改变物理地址。)
请注意,这些问题存在于面向对象编程范式变得普遍之前,并且是面向对象编程的动机之一。面向对象编程不是凭空发明的任意宗教教义,而是通过大约60年的编程经验过滤出的一组原则。