簡體   English   中英

與Java Encapsulation Concept混淆

[英]Confused with Java Encapsulation Concept

美好的一天!

我正在閱讀一本關於封裝的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方法並在另一個類上分配值,那會更好嗎? “隱藏數據”是什么意思?

謝謝。

您可以使用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
  }

}

是的,不是。 封裝的關鍵是它可以防止其他類需要知道你的類在幕后做了什么。 如果你將你的name存儲在一個String (就像你在這里所做的那樣),從一個文件中讀取/寫入它,或者做一些不同的事情,封裝的重點在於你的類用戶無關緊要,因為它們都是 see是String getName( )void setName (String name)

由於數據的修改完全在您的類的控制之下,因此它不會破壞封裝。 如果您確實name存儲到文件中,那么您可以在getAllInfo執行此操作,而不getAllInfo任何其他用戶更聰明。 由於來自類外部的可觀察行為仍然隱藏了類的內部正在做什么,它仍然被封裝。

也就是說,這是一種非常規的方法。 就像我在第一段中描述的那樣,使用訪問器方法(getter和setter)是一種更慣用的方法,對於使用您的代碼的其他人來說更容易理解。 你可以做你做的事情,它不會破壞封裝,但它不是我稱之為優雅或典型的東西。

私有類成員(屬性,字段)的想法是僅在聲明類(而不是實例!)中直接訪問它們。 所有其他類都必須使用其他訪問器,例如getter和setter方法。 所以, 如何的方式AdressBookEntry存儲姓名,地址,telNo和電子郵件的價值觀,是完全隱藏在類中。

不必使用的getter或setter方法,雖然有時也有充分的理由對類里面也這樣做。 如果在設置值之前進行某些日志記錄或驗證,則使用getter和setter有時會有意義。

這不違反封裝,因為它不會將內部數據暴露給另一個類。 您可能希望查看模型 - 視圖 - 控制器 (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: "));

我同意所提供的所有重要答案。 我想增加使用封裝的另一個好處,就是通過隱藏客戶端的數據 (就像上面描述的例子一樣),你可以保證如何設置和獲取這些實例變量,使你的類更容易維護和測試(即如果您有許多客戶端操作對象變量,則不需要逐個類地編寫新功能,而只需修改getter和setter)。

通過僅使用對象setter和getter,可以從外部世界隱藏其實現的細節。 這是一個很好的優勢,因此嘗試與您的類​​交互的其他對象將無法破壞其功能。 這也增加了系統有效實施的可能性。

我發現上面的答案已經回答了你的問題。 但是,我發現您的代碼存在另一個問題,即安全性和數據完整性問題。 您將直接從用戶的輸入中填寫您的類成員,無需對其進行任何驗證。 例如,您可能想要檢查電子郵件地址是否具有xyz@abc.com模式。 惡意用戶還可能在輸入中提供非常長的字符串,從而導致意外錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM