12

伙计们,我首先要道歉,因为我确信这已经在其他地方得到了回答——我只是找不到以我理解的方式解释它的答案!我正在上一门理学硕士转换课程,有一些基本的基础知识我仍在为此苦苦挣扎,包括这个 - 为什么将变量设为私有更好。

假设我有一个名为 Person 的 Java 类,带有一个 print 方法。我可以创建它并将其定义为:

public class Person
{
    public String name;
    public String telephoneNumber;

    public void print()
    {
       System.out.println(name + " " + telephoneNumber);
    }
}

然后,在主类中,我可以编写以下代码:

class testPerson
{
  public static void main(String[] args)
  {
    Person test;
    test = new Person();

    test.name = "Mary";
    test.telephoneNumber = "01234 567890";

    test.print();
  }
}

如果我这样做了, test.print(); 将产生输出:

mary 01234 567890

但是,我知道这被认为是糟糕的编码。变量在公共类中应该是私有的,因为我们不想让人们看到这些信息是如何存储的,或者在未经授权的情况下能够编辑信息。

所以现在,我将编辑 Person 类以将两个字符串声明为私有并添加 get 和 set 方法,如下所示:

private String name;
private String telephoneNumber;

public void setName (String name)
{
  this.name = name;
}

public void getName()
{
  return name;
}

// same code for telephone methods.

现在,在主类中,我将设置姓名和电话的方法更改为以下内容:

mary.setName("Mary");
mary.settelephoneNumber("01234 567890");

根据我正在关注的讲义,这更有效(尽管可以通过添加 Person() 方法以允许实例化等来提高效率)

但是,我很难理解为什么这会更好。
在前一种方法中,用户可以直接访问变量。但是,即使通过隐藏他们无法直接访问的变量,用户也可以间接访问和修改它们,从而产生完全相同的结果。

为什么这是首选,毫无疑问我错过/忽略了什么愚蠢的事情?

4

5 回答 5

30

比萨送货类比

  1. 您订购了一份披萨送餐。
  2. 比萨男孩敲门,希望你付钱。
  3. 你从钱包里拿出钱,交给送货员。(您可以控制隐藏内部详细信息(驾驶执照等))或者,
    • 你可以把钱包交给送货员,让他从里面取钱。通过这样做,您将不再处于控制之中。您正在暴露内部细节。

阅读信息隐藏封装不是信息隐藏

于 2013-02-04T20:34:26.063 回答
14

并不是说它更高效,而是它更易于维护并且是一个好的实践。

例如,使用 setter 方法,您可以在实际进行设置之前setTelephoneNumber实际检查是否String是有效的电话号码。如果您将变量公开,则不可能这样做。从一开始就使用 setter 意味着您可以稍后返回并添加验证,而如果您将变量公开,则必须添加 setter 并修改所有用户以使用 setter 而不是修改直接变量。

于 2013-02-04T20:28:37.707 回答
5

人们会给你一百万个为什么它更好的反刍理由,但它只是在某些情况下更好,而不是在所有情况下都明确。例如,以 Java 自己的类为例GridBagConstraints——它根本没有方法(如果你不计算clone,它无论如何都有;所有 Java 类都继承自它Object)。为什么?因为有一种情况实际上更实用。并且GridBagConstraints是最纯粹意义上的 Java Bean:它完全是关于属性的,没有业务逻辑。

让我从实践中报告另一个事实:没有 setter 验证其输入;没有 getter 计算过它的结果。在 JavaBeans 的世界中,任何这样的行为很快就会妨碍setter set 和 getter get的普遍假设。基本上,如果您以任何方式偏离与公共领域完全等价的内容,您就输了。

现代 Java API,如 Hibernate,通过在与 JavaBean 样式属性平等的基础上接受裸公共字段来承认这一事实。早期版本不允许这样做,但随着 Java 经验的积累,人们终于意识到公共字段是可以的

于 2013-02-04T20:34:04.753 回答
2

您必须假设,在某个时候,其他人会使用您的代码 - 并且其他人可能是您,一年后。如果你在一个类上看到一个公共属性,你应该能够假设它是你可以自由操作的,如果它不被直接修改,你不应该能够在外部看到它。

一个很好的文字示例是位图对象的尺寸。如果您尝试绘制尺寸为-10x-10 的位图,大多数机器都不会喜欢它,因为这样的东西显然不可能在屏幕上表示。如果此位图的宽度/高度属性只是公共变量,则它们可能会被善意的编码器稍后设置为无效值(永远不要假设它不会发生),并且在渲染它时 -砰,你有一台冻结的电脑。

通过隐藏变量并使用 setter,您可以防止这种情况发生:

private int _width = 10;

public void setWidth(int value)
{
     //Prevent the value moving into invalid range:

     if(value < 1)
          value = 1;

     if(value > 4096)
          value = 4096;

     //Now apply it
     _width = value;
}

但是,为了速度和方便,您不必一开始就像这样开发您的代码 - 只需确保您之后通过它并隐藏您需要的内容!

于 2013-02-04T20:51:04.490 回答
0

还有安全问题需要考虑。一个常见的例子是银行账户。你有余额,你用存款来存钱,用取款来取钱。如果余额是公开的,则可以在不存入或取款的情况下对其进行修改。那可能非常糟糕。

在一个方法中,您可以对事物进行检查,例如确保您从帐户中取出的资金不会超过实际存在的金额。如果您直接访问这些值,您将无法真正做到这一点。这是关于控制。

于 2013-02-04T20:36:47.673 回答