310 likes | 411 Views
計算機與工程問題解析導論. 第七課 方法 字串 建構子 this 繼承. Java 的方法. 方法是類別間的介面或溝通 提供你的程式可從許多地方來喚起相同的的操作以避免重複的程式碼 對方法的使用者或呼叫者隱藏了執行時的細節 方法中定義的變數對方法的呼叫者而言是不可視的;他們 ( 譯者按:方法內的變數 ) 在方法內有 局限性的範圍 (local scope) 方法同樣也看不見在呼叫者的中的變數。兩者 ( 譯者按:方法與其呼叫者的變數 ) 間有邏輯上的分隔,在於避免變數名稱的衝突。. 喚起方法. public class Power1 {
E N D
計算機與工程問題解析導論 第七課 方法 字串 建構子 this 繼承
Java 的方法 • 方法是類別間的介面或溝通 • 提供你的程式可從許多地方來喚起相同的的操作以避免重複的程式碼 • 對方法的使用者或呼叫者隱藏了執行時的細節 • 方法中定義的變數對方法的呼叫者而言是不可視的;他們(譯者按:方法內的變數)在方法內有局限性的範圍(local scope) • 方法同樣也看不見在呼叫者的中的變數。兩者(譯者按:方法與其呼叫者的變數)間有邏輯上的分隔,在於避免變數名稱的衝突。
喚起方法 • public class Power1 { • public static void main(String[] args) { • double a= 10.0, b; • int x= 3; • System.out.println("Main: a= " + a + ", x= " + x); • b= power(a, x); • System.out.println("Main: Result b= " + b); • } • public static double power(double d, int i){ • System.out.println("Power: d= " + d + ", i= " +i); • double x= d; // 這個 x 是不同於 main方法中的 x • for (int j= 1;j < i; j++) • x *= d; // x = x* d; • return x; } • }
傳遞引數 只透過引數溝通, 並傳回值 以位置來確認引數 引數2 引數1 傳值 假設方法是先被撰寫完成的:也就是並不知道main()方法的變數。 //方法暗自複製了 d 和 i
傳值呼叫 • Java 在傳遞引數到方法時僅支援「傳值呼叫」: • 方法會複製每一個引數 • 然後使用複製的引數進行運算 • 方法無法改變呼叫它自身的引數值(變數)
傳值呼叫 • 方法只能傳回訊息給呼叫者 • 透過回傳的值,以及 • 改變傳給方法的物件中的資料(稍後會介紹更多) • 回傳的值可以是空的,意即沒有東西回傳。方法main()就回傳空的值。 • 另外的機制,像其它語言及C++所支援的,稱為傳參考位址呼叫,它允許方法改變引數。
傳值呼叫的範例 • public class CallByValue { • public static void main(String[] args) { • int i= 3; • double d= 77.0; • System.out.println("Main 1: i= " + i + ", d= " + d); • triple(i, d); // 沒有回傳值 • System.out.println("Main 2: i= " + i + ", d= " + d); • // 範例的第二部份: 改變引數 • triple(i, i); // 好 - Java 轉換整數為雙精度 • System.out.println("Main 3: i= " + i); • } • public static void triple(int ii, double dd) { • System.out.println(“Triple 1: ii= " +ii+ ", dd= " +dd); • ii *= 3; // ii= ii*3; • dd *= 3.0; • System.out.println(“Triple 2: ii= " +ii+ ", dd= " +dd); • } • }
跟隨物件的傳值呼叫 • public class CallObjExample { • public static void main(String[] args) { • Demo d= new Demo(3); • int i= 3; • System.out.println("Main1: i= " + i + ", d.a= " + d.a); • triple(i, d); // 無回傳值 • System.out.println("Main2: i= " + i + ", d.a= " + d.a); • } • public static void triple(int ii, Demo dd){ • System.out.println("T1: ii= "+ ii + ", dd.a= " + dd.a); • ii *= 3; // ii= ii*3; • dd.a *= 3; • System.out.println("T2: ii= "+ ii + ", dd.a= " + dd.a); • } • }
跟隨物件的傳值呼叫 class Demo { // 設定為public只為表示傳值呼叫 public int a; public Demo(int aa) { a= aa; } }
方法的用法 • 方法的引數的名錄(list)與名稱就稱為方法的「用法」 • 在類別中,只要有不同的「用法」,方法可以有相同的名稱。 • 在類別中,所有相同名稱的方法一定會有相同的回傳型態。
方法的覆載 • 使用相同的方法但是有不同的「用法」就稱為「方法覆載」。 • Java是根據在方法中所引用的引數數目、型態及順序來決定哪一個被覆載方法的版本。 • Java會「提昇」數字資料型態來「向上」符合用法。
字串類別 • 是Java系統的一部份 • 字串類別有特別的連續運算子 • 字串允許常數的初值,例如 String teststring = “Hello”; String 在建立後就不可修改 – 「永遠不變的」
字串 • public class StringExample { • public static void main(String[] args) { • String first= "George "; • String middle= "H.W. "; • String last= "Bush"; • String full= first + middle + last; • System.out.println(full); • // 測試字串的相等 (一般的物件) • String full2= "George H.W. Bush"; • if (full.equals(full2)) // 正確的表示 • System.out.println("Strings equal"); • if (full == full2) // 錯誤的表示 • System.out.println("A miracle!"); • if (first == “George ”) //錯誤的表示,但是可以作用System.out.println("Not a miracle!");
字串 • // 修改字串一定要用間接的方式才能完成 • // 字串是常數 • middle = middle.substring(0, 2) + " "; • full= first + middle + last; • System.out.println(full);} • }
「this」 – 物件如何自我參考 • 物件可以被稱為參考的變數來存取。 • 假定在物件中撰寫程式碼,我們要參考回來這個物件。 • 例如:假定我們要傳遞一個參考到「自己」就像另一個物件的方法的引數一樣
this • “this”也可當成是對這個類別而言參考到其他的建構子的簡述
建構子中的 this • public class SimplePoint { • private double x, y; // 資料成員 • public SimplePoint() { // 建構子 • x= 0.0; • y= 0.0; } • public SimplePoint(int x, int y) { • this.x = x; • this.y = y; } • // 方法 • public double getX() { return x;} • public double getY() { return y;} • public void setX(double xval) { x= xval;} • public void setY(double yval) { y= yval;} • public void move(double deltaX, double deltaY) { • x += deltaX; • y += deltaY; } • } // 類別 SimplePoint 結束
彈簧 壓力作用 張力作用 扭力作用 力 = 彈性係數 * 變位
類別彈簧的建構子 • class Spring { • private String material= “steel”; // 初始化 private double length; // 只考慮壓縮 private double maxDeflect; • private double k; • public Spring(String m, double len, double md, double k) { • material= m; • length= len; • maxDeflect= md; • this.k= k; // “this” • } • public Spring(double len, double k) { • this("steel", len, 0.25*len, k); // “this” • } • public Spring(double len) { • this(len, 0.5*len); • } • public Spring() { • this(10.0); }
類別彈簧的方法 public String getMaterial() { return material; } public double getLength() { return length; } public double getMaxDef() { return maxDeflect; } public double getK() { return k; } // 不需要 ‘this’ public void setMaterial(String m) {material= m; } public void setLength(double len) {length= Math.abs(len);} public void setMaxDef(double m) {maxDeflect= Math.abs(m);} public void setK(double k) {this.k= k; } // this public double getForce(double deflection) { if (deflect > maxDeflect) deflect= maxDeflect; return k*deflect; } public double getForce() { // 覆載方法 return k*maxDeflect; } }
彈簧的 main() 方法 • public class SpringExample { • public static void main(String[] args) { • Spring one= new Spring("aluminum", 2.0, 1.0, 5.0); • Spring two= new Spring(5.0, 3.0); • Spring three= new Spring(); // 3 個不同的建構子 • double f1= one.getForce(0.5); • double f2= two.getForce(1.5); • double f3= three.getForce(0.1); • System.out.println("f1: " + f1 + "\nf2: " + f2 + • "\nf3: " + f3); • double f4= one.getForce(); // 超載的方法 • double f5= two.getForce(); • double f6= three.getForce(); • System.out.println("f4: " + f4 + "\nf5: " + f5 + • "\nf6: " + f6); • System.exit(0); • } • }
彈簧類別的設計 • 彈簧所有的方法均為公用的 • 任何類別的方法均可呼叫這些方法 • 私用方法可以被使用,但只有這個類別自己可以用來當作幫手或手法 • 彈簧中的資料欄位是私用的 • 只有彈簧的方法可以使用它們 • 公用資料欄位幾乎不可被使用 • 建構子的名稱必須與類別名稱一致 • 建構子只能用「new」來呼叫 • 建構子不能回傳值
彈簧類別的方法 • 為何有這些方法? • 因為方法 Get 只能從其它類別中使用到彈簧的資料 • 如果需要的話,可以讓我們重新執行彈簧 • 方法 Set 應該要檢查錯誤 • 我們的方法應該確認:長度要大於0, 最大的變形要小於長度等等。 • 覆載方法時必須有不同的使用(引數) • 不同的回傳型態並不能分辨兩個一樣的分法 • int getForce(int a) 與 • double getForce(int b) 將無法編譯
物件的解構 • 當沒有主動的參考到物件時,Java會自動地利用「垃圾收集」將物件所佔的記憶體收回 • C++則需要程式人員以手動方式來做。在C++中你會謹慎地使用「new」是因為必須在使用完後使用「delete」來避免「記憶體漏失」 • 當物件被銷毀時,Java有終結器來清除其它的資源(檔案、鎖定的設備等) • 非正式的忠告:千萬不要使用終結器 • 終結器會喚起任何物件導致垃圾收集器效率低落
梁的練習 撰寫一個 Java類別來建構梁的模型以及計算它的最大橈度: w=-PL3/3EI 其中 P=端點載重(1200N) L=梁長(20m) E=彈性模數(30000N/m2) I=慣性力矩(1000m4) w=橈度(m)
梁的練習(續) • 資料欄位: • 哪些是梁的特性? • 哪些是外在的? • 撰寫兩個建構子 • 一個以所有的欄位當引數 • 引數與欄位使用相同的名稱 • 一個只用長度為引數 • 其它的欄位用前述的數值做為預設值 • 使用”this”來喚起其它建構子或依賴起始程序 • 在類別中使用起始程序:假定你正在處理許多像範例的梁 • 撰寫兩種方法來回傳橈度值w • 兩種都使用相同方法的名稱(覆載) • 以個以載重為引數,第二個將載重與單位(英呎或公尺)當做字串;轉換時1m=3.3ft • 不要撰寫任何的get或set方法 • 撰寫一個含有main()的類別來建立梁,並計算梁的橈度並列印結果
梁的練習(續) • 選擇性的,進階的: • 加入尺寸分析: • 儲存類別中每個變數的單位 • 決定你會如何將它們編碼(指數…等等) • 修改建構子接受單位引數 • 如所需要轉換單位(N-lf, m-ft) • 1lbf=4.4N, 1ft=o.3m • 確認在計算中單位相符 • 輸出單位時要加上方法結果
梁的類別 • class Beam { • private double L; • private double E= 30000.0; // 初始程序 • private double I= 1000.0; • public Beam(double L, double E, double I) { • this.L= L; // this 來存取資料 • this.E= E; • this.I= I; • } • public Beam(double L) { • this.L= L; // 其它的靠起始程序 • } // 可以使用 this(L, 30000., 1000.); • public double getDeflection(double P) { • return -P*L*L*L/(3.0*E*I);} • public double getDeflection(double P, String u) { • if (u.equals("ft")) // not == • return -3.3*P*L*L*L/(3.0*E*I); • else return -P*L*L*L/(3.0*E*I); • } • }