与Java Encapsulation Concept混淆

时间:2011-02-18 06:31:18

标签: java encapsulation getter-setter

美好的一天!

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

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

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方法并在另一个类上分配值,那会更好吗? “隐藏数据”是什么意思?

谢谢。

6 个答案:

答案 0 :(得分: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
  }

}

答案 1 :(得分:5)

是和否。封装的关键是它可以防止其他类需要知道你的类在幕后做了什么。如果你将name存储在String中(就像你在这里所做的那样),从文件中读取/写入,或者做一些不同的事情,封装点就是你班级的用户这没关系,因为他们看到的所有都是String getName( )void setName (String name)

由于数据的修改完全在您的类的控制之下,因此它不会破坏封装。如果您 name存储到文件中,那么您可以在getAllInfo中执行此操作,而不会让该类的任何其他用户更明智。由于类的外部的可观察行为仍然隐藏了类的内部所做的事情,因此它仍然被封装。

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

答案 2 :(得分:3)

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

你没有来使用getter或setter,尽管有时也有很好的理由在课堂上这样做。如果在设置值之前进行一些记录或验证,则使用getter和setter有时会有意义。

答案 3 :(得分: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: "));

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

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