# getter和setter方法 getter()或setter()方法 getter()和setter()方法是種名詞上的泛稱,用比喻的來說,就是指一個類別(或物件)之中,private屬性(成員變數)的管家。 由於private屬性非常自閉,完全不與同一類別(或物件)以外的任何事物互動,因此只好委託這兩個和它在同一類別(或物件)之內的管家代勞,協助管理private屬性與外界的「溝通」。而這兩個管家,getter()負責將private的資料傳出到外部,也就是外部的物件可以透過getter()這位管家得到private屬性的資料,相當於送件員;而setter()正好相反,它負責接收外部的資料,並將處理過後的資料傳遞給private變數,相當於審查者。 而無論是getter()或是setter(),其實也就是一般的public方法(成員函數),所以我們可以為它們定義實作的程式碼,告訴它們要如何運算、處理資料,之後才去存 / 取private屬性。也就是說,這個送件員或審查員,可以經過把資料改寫、處理的動作後,才去存 / 取private屬性,保護它不被隨意亂動,但又達到可以使用它的目的,也就是說getter()或setter()是作為private屬性輸入 / 輸出的控制方法。 想當然爾,這兩個管家(getter & setter)一定要是public的,這樣它們才有辦法與外界互動,不能連管家都搞自閉。 幹嘛這麼多此一舉?我們一開始就把屬性宣告為public的不就得了?這樣說是對的,不過通常只適用於單人開發小型程式的時候,自己非常清楚在做些什麼,便於管理和修改。但在真正的工作場合,公司都是以團隊、多人協作來開發專案,若你有一個或數個屬性(成員變數)的值不想被其他人任意修改,就可以自己定義getter()和setter()方法作為管家,讓別人只能用你所定義的方式「安全的」存 / 取private屬性。 這麼做的好處還不只於此,適當的定義getter()和setter()方法可以提高程式的可讀性,也讓程式變得更加系統化、結構化,未來要維護或擴充新功能也都變得更容易,並且適合不斷變更與新增需求的實際工作情況。 其實getter()和setter()方法只是個名詞上的泛稱,我們可以將用來存 / 取private屬性的public方法,任意命名為自己喜歡的名稱,因此getter和setter的概念其實我們可能已經用很多次了,只是不知道原來它還有一個術語叫作getter和setter而已。 我們也可以不用兩個都定義,若我們只定義了getter()方法,則這個private屬性就變成「唯讀」的,只能讀取而不能寫入,還蠻常用到;同理,若我們只定義setter()方法,則這個private屬性就變成只能寫入而不能讀取,但一般比較少需要這麼做。 實際範例: public class Circle { // 定義一個Circle(圓)類別 private double radius; // 定義private屬性radius private double pi = 3.14; // 定義private屬性pi public double getpi() { //定義一個可讀取private屬性的public方法(getter) return pi; } public void setRadius(double radius){ //定義一個可寫入private屬性的public方法(setter) this.radius = radius; } public double getC() { return 2 * pi * radius; // 定義一個可讀 / 寫private屬性的方法,計算圓周長 } } getter()和setter()其實就是泛指一般可用來存 / 取private屬性的public方法,只是個術語而已,我們可以任意命名。要複雜一點的話,當然也可以在其定義內加入更複雜的運算、邏輯判斷…等敘述,要把getter()和setter()的定義寫的多複雜都行。 補充一下,有一種作法稱之為「緊密封裝」,意思就是,把類別或物件內所有屬性的權限都設成private,並只提供 public method或Get & Set存取器來供外界操作變數,也就是把資料看管的很緊的意思。 * 註:一旦Property或Method的權限被設為 Private,那就只有同一個class的{ }大括號範圍內的東西才有權限存 / 取。 ----------------------------------------------------------------------------------------- 補充說明:C# 中的get{ }和set{ }存取管理器 我們前面說getter和setter只是個廣泛的術語,代表用public方法(成員函數)來存/取private屬性(成員變數),也就是說在Java中並沒有關鍵字代表這兩個操作。 不過在C# 就不同了,C# 是真的有get和set這兩個關鍵字,可以用這兩個關鍵字來做到getter和setter的操作,並且還有專屬的語法。和一般方法(成員函數)不同,C# 的get和set關鍵字後面是緊跟著大括號{ }的,並且要寫在某個屬性(成員變數)的下方。而且,無論這個屬性是public或private或protected…等都可以用,並不只限於private。 至於觀念就和Java一樣,如果要存/取這個有get{ }或set{ }管控的屬性,就一定要先通過它們這一關才行。雖然沒有get和set這兩個關鍵字也沒關係,就和Java一樣去用就好,但C# 這樣的設計,微軟認為可以更加強調出該屬性和它的get{ }或set{ }存取管理器之間的關聯性,可讓程式碼更加精簡、更加易讀易懂,至於是不是真的這樣,就見人見智了。 以下我們以C# 的語法來實作get{ }和set{ }存取管理器: private int hp ; public int HP { // 在想管理的屬性下方用{ }包住get{ }和set{ } get{ return hp ; } // 在讀取HP時會先被執行(也可應用於public屬性) set{ // 在存入數值時會先被執行 if(value < 0) hp = 0; else hp = value ; } } // 用{ }包住get{ }和set{ } 注意get{ }和set{ }不是方法(成員函數),而是某個屬性的「存/取管理器」,而且它們後面跟的是{ }括號而不是()括號,所以要把get{ }和set{ }當做一種特殊的東西來看待。 以上是在C# 用關鍵字get和set來實作的,但如果不使用get和set關鍵字也是可以,例如以下這段程式碼,就是用定義方法(成員函數)的方式來實作,也可以達到相同的效果: private int hp ; public int getHP() { return hp; } public void hurt(int decreaseHP) { if (hp >= decreaseHP) hp -= decreaseHP ; else hp = 0 ; } 至於實際上要怎麼去撰寫就見人見智了,可依照個人的習慣或喜好,或是開發團隊的要求去做。