[英]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.