4

再会!

我正在阅读一本关于封装的 Java 书籍,其中提到了 getter 和 setter 方法。

我已经读过要隐藏属性,我必须将我的实例变量标记为“PRIVATE”并使用“PUBLIC”方法getter and setter来访问数据。所以我尝试制作一个类似但不是常规的代码,如下所示:

public class AddressBookEntry {

    private String name;
    private String address;
    private String telNo;
    private String email;

    public void getAllInfo() {
        name = JOptionPane.showInputDialog("Enter Name: ");
        address = JOptionPane.showInputDialog("Enter Address: ");
        telNo = JOptionPane.showInputDialog("Enter Tel. No: ");
        email = JOptionPane.showInputDialog("Enter Email Address: ");
    }
}

我上面的代码是否公开了我的变量,因为我直接分配了它?我怎样才能做得更好?如果我getter and setter改用传统方法并将值分配给另一个类会更好吗?“隐藏数据”是什么意思?

谢谢你。

4

6 回答 6

7

您使用 setter 和 getter 使变量可以从您的类外部访问。在您的示例中,您将拥有

public class AddressBookEntry {

    private String name;

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

    public String getName() {
       return name;
    }
}

您将从 UI 类访问 name 属性(在同一个类中混合 UI 和业务逻辑是不好的):

public class MyPane extends JFrame {

  public getAllData() {
     String name = JOptionPane.showInputDialog("Enter Name: ");
     AddressBookEntry entry = new AddressBookEntry();
     entry.setName(name);
     // You can't use entry.name = name
  }

}
于 2011-02-18T06:39:43.487 回答
5

是和不是。封装的重点是它可以防止其他类需要知道你的类在幕后做什么。如果你将你的存储name在一个String(就像你在这里所做的那样),从一个文件中读/写它,或者做一些不同的事情,封装的重点是对你的类的用户来说这并不重要,因为他们看到的只是String getName( )void setName (String name)

由于数据的修改完全在你的类的控制之下,它不会破坏封装。如果您确实存储name到文件,那么您可能会这样做,getAllInfo而该类的任何其他用户都不会更聪明。由于从类外部观察到的行为仍然隐藏了类内部在做什么,所以它仍然被封装。

也就是说,这是一种非常规的方法。就像我在第一段中描述的那样,使用访问器方法(getter 和 setter)是一种更惯用的方法,并且对于使用您的代码的其他人来说更容易理解。你可以做你所做的,它不会破坏封装,但这不是我所说的优雅或典型。

于 2011-02-18T06:38:35.090 回答
3

私有类成员(属性、字段)的想法是直接在声明类(而不是实例!)内部访问它们。所有其他类都必须使用其他访问器,例如 getter 和 setter 方法。因此,存储姓名、地址、电话号码和电子邮件值的方式AdressBookEntry完全隐藏在类中。

您不必使用getter 或 setter,尽管有时在类中也有充分的理由这样做。如果您在设置值之前进行一些日志记录或验证,有时使用 getter 和 setter 是有意义的。

于 2011-02-18T06:37:45.583 回答
1

这不会违反封装,因为它不会将内部数据暴露给另一个类。您可能希望查看Model-View-Controller (MVC),以帮助将您的界面与数据分开。

传统上,您可以根据需要为每个变量创建一个 getter 和 setter,如下所示:

public String getName() {
  return name;
}

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

不要为不需要在类外访问的变量创建 getter,也不要为不需要在类外设置的变量创建 setter。

如果遵循 MVC 并使用上面的传统 getter 和 setter,您将在其他地方查看代码并调用类似

myAddressBookEntry.setName(JOptionPane.showInputDialog("Enter Name: "));
于 2011-02-18T06:37:31.383 回答
1

我同意提供的所有出色答案。我想补充一下使用封装的另一个好处,即通过对客户端隐藏数据(就像上面描述的示例一样),您可以保证如何设置和获取这些实例变量,从而使您的类更易于维护和测试(即,如果您有许多客户端操作您的对象变量,您不需要逐个类地编写新功能,而只需修改getter 和setter)。

通过仅使用对象的 setter 和 getter,可以对外界隐藏其实现的细节。这是一个很好的优势,因此其他尝试与您的类​​交互的对象将无法破坏其功能。这也增加了系统有效实施的可能性。

于 2011-02-18T08:06:33.230 回答
1

我发现上面的答案已经回答了你的问题。但是,我发现您的代码存在另一个问题,即安全性和数据完整性问题。您正在直接从用户的输入中填写您的班级成员,而无需对其进行任何验证。例如,您可能想要检查电子邮件地址是否具有 xyz@abc.com 模式。恶意用户还可能在输入中提供很长的字符串,从而导致意外错误。

于 2011-02-20T08:35:17.330 回答