Java OOP Public vs Private vs Protected

时间:2011-12-11 02:21:51

标签: java oop class variables methods

我了解公共,私人和受保护的行为。我知道您应该使用它们来遵循面向对象编程的概念,并且我知道如何在使用多个类的程序中实现它们。

我的问题是:为什么我们这样做?为什么我不能直接修改另一个类的全局变量?即使你不应该为什么保护,私人和公共修饰符甚至是必要的?这就好像程序员不相信自己不这样做,即使他们是编写程序的人。

提前致谢。

6 个答案:

答案 0 :(得分:9)

你是对的,因为我们不能信任自己。可变状态是计算机程序复杂性的一个主要因素,它很容易构建起初看起来不错的东西,随后随着系统变大而变得失控。限制访问有助于减少对象状态以不可预测的方式发生变化的机会。这个想法是让对象通过明确定义的渠道相互通信,而不是直接调整彼此的数据。这样我们就有了测试单个对象的一些希望,并对它们作为更大系统的一部分的行为有了一定的信心。

答案 1 :(得分:6)

让我举一个基本的例子(这只是为了说明):

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

  }
}

现在,您不仅可以进行检查,还可以提供信息性异常,这有助于在早期阶段快速发现错误。

这只是其中一个例子,OOP(Encapsulation,Abstraction等)的基础知识,帮助您标准化界面并隐藏底层实现。

答案 2 :(得分:4)

请记住,编写给定类的开发人员可能不是唯一使用它的人。开发人员团队编写软件库,这些库在Java中通常作为JAR分发,由完全不同的开发团队使用。如果没有这些标准,其他人很难至少知道任何可用变量/方法的意图。

例如,如果我有一个私有/受保护的实例变量,我可能有一个公共的“setter”方法来检查有效性,前置条件并执行其他活动 - 如果任何人可以自由修改,那么所有这些都将被绕过实例变量直接。

另一个好处是Java文档/教程:http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

  

公共字段倾向于将您链接到特定的实现和   限制您更改代码的灵活性。

答案 3 :(得分:2)

  • 非本地行为难以推理。
  • 最小化表面积可以提高理解力。
  • 我不相信自己会记住所有的行为副作用。
  • 我绝对不会信任你#34;了解所有行为副作用。
  • 我越少暴露我必须修改和扩展的灵活性。

答案 4 :(得分:2)

  

我的问题是:为什么我们这样做?

基本上,因为以这种方式限制自己,我们会让自己和其他可能需要在将来阅读/修改代码的人更容易理解...代码,以及各个部分交互的方式。

大多数开发人员通过抽象的心理过程来理解代码;即精神上在代码位周围绘制边界,单独理解每个位,然后理解每个位如何与其他位交互。如果代码的任何部分可能会混淆代码的任何其他部分的“内部”,那么这使得典型的开发人员很难理解正在发生的事情。

在编写代码时,这对您来说可能不是问题,因为您可以在创建代码时保持头脑中所有复杂的交互。但是在一两年的时间里,你会忘记很多细节。而其他人从来没有从头开始细节。

  

为什么我不应该让一个类直接修改另一个类的全局变量?

因为它使您的代码更难理解;往上看。代码库越大,问题就越明显。

另一点是,如果您使用过度使用全局变量(实际上是静态),那么如果您的代码需要多线程/可重入,单元测试以及您需要在其他上下文中重用代码,则会产生问题。

  

即使你不应该为什么保护,私人和公共修饰符甚至是必要的?这就好像程序员不相信自己不这样做,即使他们是编写程序的人。

不是信任。它是关于在源代码中表达边界的地方。

如果我编写一个类并声明一个方法或一个字段private,我知道我不必考虑如果其他类调用/访问它/修改它会发生什么的问题。如果我正在阅读别人的代码,我知道我可以(最初)在映射交互和边界时忽略private部分。 privateprotected修饰符和包私有 提供不同的边界粒度。

(或者也许是关于信任;即不信任我们自己 记住我们设计中的抽象边界在哪里。)

答案 5 :(得分:1)

基本上有两个原因:

1)Java中存在需要安全性的接口。例如,在您的盒子上运行Java小程序时,您希望确保小程序无法访问未经授权的文件系统的某些部分。如果没有强制安全性,applet可以进入Java安全层并修改自己的权限。

2)即使每个人都“信任”,有时权宜之计也胜过常识,程序员绕过API来访问内部接口,而不是增强API(事实上,这通常需要更长的时间)。这会给稳定性和升级兼容性带来问题。

(在古代计算历史的深处,有一个传奇,一个由应用程序员以这种方式处理的操作系统,在某种程度上,维护操作系统的程序员被迫确保某些代码段(不是入口)当操作系统被修改时,点,但实际的内部代码序列)没有改变物理地址。)

请注意,在OOP范例变得普遍之前存在这些问题,并且是OOP的一些动机。 OOP不是一种凭空发明的任意宗教教义,而是一系列已经过大约6年编程经验的原则。