
為什麼要這麼做呢?理由其實很簡單,為了防止物件遭不當的使用,例如
Encrypt t = new Encrypt(); t.cArray = { 'a' }; // 重新將 cArray 設定為另一個陣列 |
Encrypt 型態的變數 t 先以沒有參數版本的建構子 (constructor) 建立新物件,然後突然將 cArray 重新設定為對另一個陣列的參考,這樣一來,原先的對換表格就不見了說,往後加入編碼與解碼的方法,使用錯誤的表格,就會造成難以回復的結果。雖然這是我們刻意弄的例子,自己寫程式真實情況常常會有打錯字之類的,例如原本要將 a 設定為 1 ,結果按成 0
t.a = 0 ; // 把 a 設定錯誤 |
當然,我們自己開發程式可以自己小心點就好,但是,假如我們的類別準備提供給別的程式設計師或開發團隊使用的話,別人就不見得會這麼小心了。因此,物件導向程式設計 (object-oriented programming) 中提供封裝的意義即在此,類別的屬性應該宣告為 private
private char [] cArray = new char [ 26 ]; private int a; private int b; private int n; private char c; private int diff; |
六個屬性就需要六個宣告為 public 的 getter 方法
public int getA() { return a; } public int getB() { return b; } public int getN() { return n; } public char getC() { return c; } public int getDif() { return diff; } public char [] getArray() { return cArray; } |
注意,建構子不需要回傳值型態,方法定義時需要標明回傳值型態,如果沒有回傳值,就須標上 void ,如另外六個 setter 方法
public void setA( int arg) { a = arg; } public void setB( int arg) { b = arg; } public void setN( int arg) { n = arg; } public void setC( char arg) { c = arg; } public void setDif( int arg) { dif = arg; } public void setArray() { int i, d, ci, m; char r; for (i = 0 ; i < n; i++) { ci = getC(); d = ci * getA() + getB(); m = d % getN(); r = ( char ) (m + getDif()); cArray[i] = r; c++; } } |
我們在 setter 中直接設定屬性值,由於參數名稱全都採用 arg ,因此這裡可以用屬性名稱,不需要用到 this 。其中包含我們之前就介紹過 setArray() ,它也是 setter 方法之一,原先直接使用屬性名稱,這裡全部改成 getter 。
有關檢查 a 是否為奇數的部份,也可以寫進 setter 之中,但是我們把這部份寫在建構子裡,當然,這兩種方式都是可行的,讀者可自行選擇想要用哪一種方式。
因此原本建構子所用的 this 就改成呼叫 setter 囉!完整的 Encrypt 修改如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | public class Encrypt { private char [] cArray = new char [ 26 ]; private int a; private int b; private int n; private char c; private int diff; public Encrypt( int a, int b, int n, char c, int dif) { setA(a); setB(b); setN(n); setC(c); setDif(dif); setArray(); } public Encrypt( int a, int b) { this (a, b, 26 , 'a' , 97 ); } public Encrypt() { int ta = 0 ; int tb = 0 ; while (ta % 2 == 0 ) { ta = ( int ) (Math.random() * 10 ); tb = ( int ) (Math.random() * 10 ); } setA(ta); setB(tb); setN( 26 ); setC( 'a' ); setDif( 97 ); setArray(); } public void setA( int arg) { a = arg; } public int getA() { return a; } public void setB( int arg) { b = arg; } public int getB() { return b; } public void setN( int arg) { n = arg; } public int getN() { return n; } public void setC( char arg) { c = arg; } public char getC() { return c; } public void setDif( int arg) { diff = arg; } public int getDif() { return diff; } public void setArray() { int i, d, ci, m; char r; for (i = 0 ; i < n; i++) { ci = getC(); d = ci * getA() + getB(); m = d % getN(); r = ( char ) (m + getDif()); cArray[i] = r; c++; } } public char [] getArray() { return cArray; } } /* 《程式語言教學誌》的範例程式 檔名:Encrypt.java 功能:示範 Java 程式 作者:張凱慶 時間:西元 2011 年 4 月 */ |
由於 cArray 已經宣告為 private ,因此 EncryptDemo 中也要改成 getArray() 才能進行測試
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // 測試 Encrypt 的類別 public class EncryptDemo { public static void main(String[] args) { System.out.println(); for ( int i = 0 ; i < 16 ; i++) { Encrypt t = new Encrypt(); System.out.println(t.getArray()); } System.out.println(); } } /* 《程式語言教學誌》的範例程式 檔名:EncryptDemo.java 功能:示範 Java 程式 作者:張凱慶 時間:西元 2011 年 4 月 */ |
請自行編譯測試,記得 Encrypt 與 EncryptDemo 都要重新編譯。接下來,我們替 Encrypt 加入編碼的功能吧!
中英文術語對照 | |
---|---|
屬性 | field |
封裝 | encapsulation |
物件 | object |
類別 | class |
宣告 | declare |
方法 | method |
建構子 | constructor |
物件導向程式設計 | object-oriented programming |
您可以繼續參考
軟體開發
相關目錄
回 Java 入門指南
回 Java 教材目錄
回首頁
參考資料
The JavaTM Tutorials: Getting Started
The JavaTM Tutorials: Learning the Java Language
The JavaTM Tutorials: Essential Classes
The Java Language Specification, Third Edition
本文於 2013 年 1 月訂正
本文於 2013 年 2 月修正
4 則留言:
您好,從頭學習java的新手,從你這邊受益良多
想跟您請教一下,在這邊將 Encrypt中加入了getter及setter之後,如果沒有對EncryptDemo做修改的話,
原本的
7 System.out.println(t.cArray);
會去存取到已經被設為private的cArray
所以在執行的時候就會得到錯誤訊息
cArray has private access in Encrypt
是不是應該也要將EncryptDemo中的段落修改成
7 System.out.println(t.getArray());
重新編譯之後,才能正確存取呢?
謝謝您的熱心指 導 :)
這部份寫錯了,已修改,感謝指正 :)
您好,#82. for (i = 0; i < n; i++) {
為何不是用getN()?
而RUN起來竟也沒有error!
謝謝指導!
這裡寫成 getN() 會比較好唷!倒是 n 或 getN() 在 Encrypt 類別裡會是同義的, Encrypt 類別外才只能由 getN() 來存取 n 。
張貼留言