2011-02-18 66 views
4

美好的一天!與Java Encapsulation概念相混淆

我正在閱讀關於封裝的Java書,它提到了getter和setter方法。

我讀過的隱藏屬性,我一定要記住我的實例變量爲「私人」,並作出「公共」的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方法,並將其他類的值賦值,會更好嗎? 「隱藏數據」的含義是什麼?

謝謝。

回答

5

是,否。封裝的要點是它可以防止其他類需要知道你的課程在幕後做了什麼。如果你將你的name存儲在String(正如你在這裏所做的那樣),從文件中讀取/寫入文件或者做一些不同的事情,封裝點對於你的班級的用戶來說並不重要,因爲所有的他們String getName()void setName (String name)

由於修改數據完全在您的類的控制之下,因此不會破壞封裝。如果你確實存儲name文件,那麼你可能會在getAllInfo這樣做,沒有任何其他用戶更聰明。由於該類的外部的可觀察行爲仍然隱藏了該類內部正在做的事情,因此它仍然是封裝的。

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

1

這不違反封裝,因爲它不會將內部數據公開給另一個類。您可能希望查看Model-View-Controller(MVC),以幫助您將界面從數據中分離出來。

傳統您爲每個變量一個getter和setter需要像這樣:

public String getName() { 
    return name; 
} 

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

不要爲不會需要類以外的地方訪問的變量創建的getter和唐」 t爲不需要在課堂外設置的變量創建setter。

如果按照MVC和使用傳統的getter和setter像上面,你將有視圖代碼的其他地方,並呼籲像

myAddressBookEntry.setName(JOptionPane.showInputDialog("Enter Name: ")); 
3

私有類成員(屬性,字段)的想法是去訪問它們直接在聲明類(不是實例!)內部。所有其他類將不得不使用其他訪問器,例如getter和setter方法。所以方式如何AdressBookEntry存儲的名稱,地址,電話號碼和電子郵件值,完全隱藏在課堂內。

你不要使用getters或setter,雖然有時候也有充足的理由在類內部這樣做。如果在設置值之前執行一些日誌記錄或驗證,則使用getter和setter有時很有意義。

7

您使用setter和getters使變量可以從您的課程外部訪問。在您的例子中,你將有

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

我同意並提供所有優秀的答案。我想添加另一個關於使用封裝的好處,並且通過從客戶端隱藏數據(就像上面描述的例子一樣),您可以保證如何設置和獲取這些實例變量,使您的類更易於維護和測試(例如,如果你有很多客戶操縱你的對象變量,你不需要按班編寫新功能,而只需修改getter和setter)。

通過只使用對象setter和getters,其實現的細節可以從外部隱藏。這是一個很好的優勢,所以其他試圖與你的類交互的對象將無法打破它的功能。這也增加了系統有效實施的可能性。

1

我發現上面的答案已經回答你的問題。但是,我發現您的代碼存在另一個問題,即安全性和數據完整性問題。你正在填寫你的班級成員,直接從用戶的輸入中取出任何驗證。例如,您可能想要檢查電子郵件地址是否有[email protected]模式。惡意用戶也可能在輸入中提供非常長的字符串,導致意外錯誤。

+0

我該如何創建電子郵件地址驗證?謝謝 – newbie 2011-02-21 01:59:05

0

術語封裝和信息隱藏可互換使用 。通過僅通過 方法公開對象功能,您可以防止您的私有變量被分配 任何不符合您的要求的值。 創建一個封裝良好的類的最好方法之一是將其實例變量 定義爲私有變量,並允許使用公開的 方法訪問這些變量。