方法進階及物件導向基礎 Lecturer: 曾學文
Outline Overloading 遞迴(Recursive) Your Turn 物件導向概念(OOP) 物件基礎
Overloading Overloading 在 Java 中有三種情況可能會造成 method 在類別中或是 superclass 中和其他的 methods 同名 覆蓋 methods(overriding methods) 遮蔽 methods(hiding methods) 名稱過載(name overloading) Overloading 為類似功能的方法統一提供一樣的名稱,但是可以根據 參數個數的不同 參數資料型態的不同 自動呼叫對應的函式。 (這樣設計員可以不用花很多心思想不同的函式名稱)
Overloading Overloading Java 中,以 method 的名稱與參數來決定一個 method 因此,Java 允許多個 methods 共用同一個名字,但必須擁有不同數目或型態的參數以供區分 例: static int square(int num) static double square(double num) 或 static int getMin(int a, int b) static int getMin(int a, int b, int c)
Overloading Example: OverloadingDemo.java static int square(int num) { return num*num;} static double square(double num) { return num*num; } static int getMin(int a, int b) { if ( a < b ) return a; else return b; } static int getMin(int a, int b, int c) { int min; if ( a < b ) min = a; else min = b; if ( min < c ) return min; else return c;
想想看一個overloading的範例 float squareMeasure(int radius) //圓形面積 { return radius* radius*3.14; } float squareMeasure(int height, int width) //長方形面積 { return height*width; float squareMeasure(int upp, int bot, float height) //梯形面積 { return (upp+bot)*height/2;
多型 (Polymorphism) 同一個介面(方法名稱),多種實際運作方法 設計一個通用的介面給一組相關動作 降低程式分類的複雜性 選擇特定的動作(也就是方法)應用於各種情況是編譯器的工作 程式設計師不需要手動去選擇 只需要記住和使用通用的介面即可
Your Turn 設計一段Code讓以下的Overloading方法 myADD 得以實現 public static void main(String[] args) { int i = 10, j = 5; int k = myADD(i, j); System.out.println("The return value: " + k); int a = 10, b=3; int w = myADD(a, b, 8); System.out.println("The return value: " + w); double y = 10.8, z=3.3; double x = myADD(y, z); System.out.println("The return value: " + x); }
遞迴(Recursive) 遞迴(Recursive) 程式設計的一個重要觀念,可以使程式碼變的很簡潔,但是設計此類方法必須很小心,不然很容易掉入無窮迴圈。 定義:一個問題內涵是由本身所定義的話,稱之遞迴 特性: 遞迴方法每次呼叫後,可使問題範圍縮小 方法必須要有一個終止條件,以便結束遞迴方法的執行
遞迴(Recursive) 遞迴的階層函數: 4! = 4*(4-1)! = 4*3! 3! = 3*2! 2! = 2*1! 1! = 1*0! = 1 2! = 2*1! = 2*1 = 2 3! = 3*2! = 3*2 = 6 4! = 4*3! = 4*6 = 24
遞迴(Recursive) Example: FactorialDemo.java static int factorial(int n) { if ( n == 1 ) return 1; else return n * factorial(n-1); }
遞迴(Recursive) 河內塔(Tower of Hanoi) 每次只能移動一個 且只能一棟最上面 任何盤子可以搬到任何 一根木樁 過程中,必須維持盤子的大小順序
遞迴(Recursive) 歸納出 3 個步驟: 終止條件:n=1 移動次數: 將最上面 n-1 個盤子從木樁 1 搬到木樁 2 將最後一個盤子從木樁 1 搬到木樁 3 將木樁 2 的 n-1 個盤子搬移到木樁 3 終止條件:n=1 移動次數: T(1)=1, T(2)=3, T(3)=7 T(n) = 2T(n-1) + 1
遞迴(Recursive) Example: TowerHanoi.java static void towerofHanoi(int dishs, int peg1, int peg2, int peg3) { if ( dishs == 1 ) { // 終止條件 System.out.println("盤子從" + peg1 + "移到" + peg3); } else { // 第一步驟 towerofHanoi(dishs-1, peg1, peg3, peg2); // 第三步驟 towerofHanoi(dishs-1, peg2, peg1, peg3); }
Your Turn 試遞迴設計 static long fib(int num) 方法來計算某一項的費氏係數 (費氏係數:1, 1, 2, 3, 5, 8, 13, 21, …) 參數 num 為欲計算的項次 提示 fib(1)=1 fib(2)=1 fib(3)=fib(1)+fib(2)=2 fib(4)=fib(3)+fib(2)=3 輸入n,就呼叫fib(n)獲得值
初步檢視類別 class: 用來訂定物件的規格 物件 = 屬性(Attributes) + 動作(Actions) I am a bird. My name is Cathy. 屬性: name, feather, claw, …. 動作: fly, sleep, eat …..
初步檢視類別 //產生物件Cathy void main() { bird Cathy = new bird() ; class bird { private: // data member string name, feather ; int claws ; public: // member functions void fly() {…} void sleep() {…} void eat() {…} } ; //產生物件Cathy void main() { bird Cathy = new bird() ; Cathy.fly() ; Cathy.sleep(); Cathy.eat() ; } 屬性 動作
Object-Oriented Programming (OOP) 類別(Class) 是一個藍圖或是原型(prototype)其中定義了某一種類別所需的狀態(variables)、行為(method)和事件(Event) 狀態(variables):一個物件的特性 (身高,體重,年齡) 物件的名詞 行為(method)或事件(event):一個物件會做的動作 (跑,跳,走路) 物件的動詞
(Object-Oriented Programming) 物件導向程式設計概念 封裝(Encapsulation) 繼承(Inheritance) 多型(Polymorphism)
封裝(Encapsulation) 結合資料(data)與處理函式為一體(物件)。 使用class 使用者不必瞭解物件中的詳細資料結構與函數實作,就可使用該物件 避免外界干擾或誤用內部資料及函式 使用private、protected及public
(封裝) 封裝 使用者: 使用Stack的push與pop功能 Stack (功能規格): push(), pop() Stack 實作一
繼承(Inheritance) 繼承(Inheritance) 一個類別可以繼承他的父類別的狀態以及行為,此時稱為此子類別(subclass)繼承於父類別(superclass) human: name, age, color eat(); sleep(); (繼承) citizen: name, age, color, country, ID eat(); sleep(); payTax(); married() ;
繼承(Inheritance) 繼承 父類別可直接透過繼承產生子類別 子類別延續父類別的功能,並可外加新功能(method) 例如:payTax(); married() ; 子類別也可以覆蓋(override)自父類別而來的功能(method),提供一個自我詮釋方式 例如: eat(); sleep(); 所以它可以覆蓋(override)父類別的原始功能,自己設定一個新的eat(); sleep(); 。
多型(Polymorphism) 編譯時期多型 執行時期多型 同一個函數名稱可以有不同的詮釋 function overloading operator overloading 執行時期多型
Object-Oriented Programming (OOP) 介面(Interface) 定義 一段只有常數與函式宣告,但沒有函式實作的程式碼。 作用 讓某個功能,不論由誰實作,都能夠有相同的函式名稱,傳入值,傳出值,與存取範圍 當某個 class 實作 interface,即代表該 class 會提供此 interface 中所有的 methods 的程式碼
物件基礎(Object Basics) 建立物件三步驟 宣告 Declaration 建構 Instantiation 語法:Class objName; 建構 Instantiation 使用 new 運算子建構新物件,此時將分配空間給此物件 初始化 Initialization 使用 new 運算子的同時,將呼叫類別建構元(constructor) 例01:String str = new String(“Hello World!”); 例02:String str; str = new String(“Hello World!”);
宣告暨實作一個Class的要點 分public和private部分 決定有哪些公開或私有的方法Method 決定有哪些公開或私有的屬性Property 宣告建構元(constructor)初始化類別的所有變數 class Cat { public int Age = 10; //有些屬性是公開的 private String animalType = “feline"; private String catColor; //有些屬性是私有的 Cat(String colorIn) // Cat 類別的建構元 {} public String getCatsColor() //Cat 提供的method {} public String getCatsType() {} }
建構函數與解構函數 建構子函數(constructor functions) 解構子函數(destructor functions) 物件生成時所自動呼叫的成員函數 解構子函數(destructor functions) 物件消滅時所自動呼叫的成員函數 垃圾收集(garbage collection)
物件的生成與消滅 1 int main() { 2 myclass ob1 ; 3 ob1.show() ; 4 fun() ; 5 return 0; 6 } 7 void fun() { 8 myclass ob2; 9 ob2.show() ; 10}
建構子 EX: 將屬於myclass的物件的初始值設為10 建構子(constructor): (1)也是成員函數 (2)與class同名 class myclass { int a ; public: myclass(); // default constructor void show() ; } ; myclass::myclass() { a= 10 ; } void myclass::show() { cout << a<<endl;} int main() { myclass ob = new myclass(); ob.show(); return 0; } 建構子(constructor): (1)也是成員函數 (2)與class同名 (3) 沒有回傳值 (4)可以有很多個 (5)允許傳參數 物件生成時,會呼叫建構子
使用物件 物件單獨宣告時可暫時不需要建構與初始化(未分配記憶體空間);但在使用物件之前,一定得建構與初始化物件 使用物件的方式 -- 物件名稱後面加 . 加成員名稱 實體變數(instance variables) 語法:objName.varName 方法(methods) 語法:objName.methodName(argList) 例如:String s = new String(“Hello World!”); s.length(); // 取出 s 這個字串物件的長度 s.charAt(0); // 取出 s 這個字串物件第一個字元
補充: 系統對物件的清除 物件的清除 在某些物件導向程式語言中,要求當物件無用時,必須明確的將其刪除,否則將持續佔據記憶體空間 Java 程式語言中,會自動偵測無用的物件,並將之刪除,稱為垃圾收集(garbage collection),此機制由垃圾收集器(garbage collector)自動執行 無用的物件可直接指定為 null 語法:objName = null; 手動立即執行記憶體清除:System.gc(); 當物件被清除掉後,它會立刻呼叫物件的 finalize 方法,在大部分情況下,系統會自動處理
產生物件並使用物件 Example: ObjectDemo.java // 產生一個 testObj 物件 Test testObj = new Test(); //建構元 // testObj 提供的 methods testObj.setX(500); testObj.printX(); testObj.printMsg("Java"); testObj.sayHello(); x = testObj.getX(); System.out.println("x = " + x);
Your Turn class Cat { public int Age = 10; private String animalType = “feline"; private String catColor; Cat(String colorIn) // Cat 類別的建構元 { catColor = colorIn; } public String getCatsColor() //Cat 提供的method { return catColor; public String getCatsType() { return animalType; Your Turn 製作一個 Cat 的類別—寫cat.java產生cat.calss 以先前寫程式的習慣製作 CatDisplay.java 在main()方法中存取 Cat 中的屬性以及方法—獲得貓的年齡、顏色、種類並列印出來