ncyu_phyedu 板


LINE

基本觀念 Encapsulation,Message Passing以及Inheritance是構成Object-Oriented的三大要素,如 果某程式語言只具備前面兩項特性,一般成為Object-Based。所謂Inheritance(繼承),是 指Sub Class(子類別)繼承Super Class(父類別)後,就會自動取得父類別特性。如果子類 別繼承了一個以上的父類別,則稱為Multiple Inheritance(多重繼承)。Java為了避開多 重繼承的複雜性, class只允許單一繼承。 Java使用關鍵字extends來表達繼承觀念: public class Animal { public String moveMethod() { return "Unspecified"; } } public class Bird extends Animal { public String moveMethod() { return "Fly"; } } public class Dog extends Animal { public String moveMethod() { return "run"; } } public class Fish extends Animal { public String moveMethod() { return "swim"; } } 若class宣告時沒有指定extends,則Java會自動extends java.lang.Object。 public class A { } 和下面的寫法相同 public class A extends java.lang.Object { } UpCasting(向上轉型)和DownCasting(向下轉型) 所謂casting是指型態轉換, UpCasting是將子類別型態的reference轉型為父類別型態, DownCasting則是將父類別型態的reference轉型成子類別型態。由於子類別可以視為和父 類別相容,如Fish, Dog, Bird都是一種Animal, 因此UpCasting一定沒有問題: Animal a; Bird b; a = b; // upcasting, Bird is a kind of Animal 父類別的reference可以指到子類別的Object,這種觀念稱為Polymorphism(多型)。 但在downcasting的情況下, 父類別的reference和子類別並不相容, 如Animal不見得是一 個Bird, 因此必須使用(SubClass)的casting語法來做強迫轉換。 Animal a = new Bird(); // upcasting Bird b; b = (Bird)a; // downcasting, compile correct if (a instanceof Bird) { // true } downcasting除了必須由設計者下達外, JVM在runtime也會檢查實際的物件能否和 reference的型態相容 Animal a = new Dog(); // upcasting Bird b; b = (Bird) a; // downcasting, compile correct, but runtime error 比較完整的範例如下 public class InheritanceExample { public static void main(String[] argv) { Animal a1, a2, a3, a4; Bird b; Dog d; Fish f; a2 = a1 = new Animal(); b = new Bird(); d = new Dog(); f = new Fish(); System.out.println(a1.moveMethod()); System.out.println(b.moveMethod()); System.out.println(d.moveMethod()); System.out.println(f.moveMethod()); a1 = b; // Correct, we call this upcasting b = a1; // Compile Error, type not compatible b = (Bird)a1; // downcasting, Compile Correct a2 = b; // Correct,we call this upcasting d = a2; // Compile Error, type not compatible d = (Dog)a2; // Compile Correct, but runtime error } } Override(覆寫) 子類別重新定義它所能看到的父類別中的method(如public, protected, 如果子類別和父 類別在同一個package裡, 則沒有修飾字的method也可以), 稱為override。 public class Animal { public String moveMethod() { return "Unspecified"; } } public class Bird extends Animal { // override Animal's moveMethod public String moveMethod() { return "Fly"; } } 要特別強調的是 如果子類別看不到父類別的方法(如父類別的private方法,或子父類別不在同一個package 而子類別定義了父類別內的package method),則就算定義了同樣的method,也不是 override 重複定義static method也不算override 子類別不可縮小父類別方法的存取範圍 public class C2 { public void a() {} } public class C1 extends C2 { protected void a() { // Compile Error,不得縮小存取範圍 } } Virtual Function(虛擬函數) 在訊息傳遞的章節裡,我們有提到過Object接收到訊息後,是在Runtime才決定實際所要呼 叫的Method。由於父類別的reference可以指到子類別物件(Polymorphism),而子類別和父 類別可能都定義了相同的Method(Override),當使用父類別reference傳遞訊息給子類別物 件時,應該要呼叫父類別的方法還是子類別的方法? 如果 呼叫子類別的方法,則稱為Virtual Function 呼叫父類別的方法,則稱為Non-Virtual Function 有些程式語言,如C++,以上兩種機制都提供,可由設計者自行決定。但是Java語言為了遵循 物件導向的精神,並避免設計者因語言設計複雜而犯錯,因此只提供了Virtual Function。 public class InheritanceExample { public static void main(String[] argv) { Animal a1; a1 = new Animal(); System.out.println(a1.moveMethod()); // print out "Unspecified" a1 = new Bird(); // polymorphism System.out.println(a1.moveMethod()); // print out "Fly" } } 請注意上一小節所提到Override的注意事項 class Animal { public static String moveMethod() { return "Unspecified"; } public static void main(String[] argv) { Animal a1; a1 = new Bird(); System.out.println(a1.moveMethod()); // print out "Unspecified" } } class Bird extends Animal { // we can't override static method public static String moveMethod() { return "Fly"; } } 上面的moveMethod()由於宣告為static,因此是依照reference的type來決定執行的method 。 class Animal { private String moveMethod() { return "Unspecified"; } public static void main(String[] argv) { Animal a1; a1 = new Bird(); System.out.println(a1.moveMethod()); // print out "Unspecified" } } class Bird extends Animal { // this is not override because Bird can't see Animal's moveMethod public String moveMethod() { return "Fly"; } } 由於上面Animal內的moveMethod宣告為private,因此執行時印出"Unspecified"。 採用Virtual Function的優點 Runtime自動尋找最特定的方法(儘量用子類別的方法),可用父類別reference呼叫到子類 別的方法,因此增加新的子類別時,不需要修改程式 缺點 執行起來比較慢 本章觀念整理範例 public class Shape2D { // define super class public double area() { // all Shape2D have their own area return 0; } } public class Rectangle extends Shape2D { private double length, width; public Rectangle(double l, double w) { // define constructor length = l; width = w; } public double area() { // Override return length * width; } } public class Circle extends Shape2D { private double radius; public Circle(double r) { radius = r; } public double area() { // Override return 3.141592654 * radius * radius; } } public class Parallelogram extends Shape2D { private double top, bottom, height; public Parallelogram(double t, double b, double h) { top = t; bottom = b; height = h; } public double area() { // Override return (top + bottom) * height / 2.0; } } publicclass Main { public static double sum(Shape2D[] shapes) { double total = 0; for (int i = 0; i < shapes.length; i++) { total += shapes[i].area(); // use Virtual Function to calculate area of Shape2D // Without Virtual Function, value of Shape2D.area() will be 0 } return total; } public static void main(String[] argv) { Shape2D[] data; // array of reference to Shape2D data = new Shape2D[5]; // create array object data[0] = new Rectangle(2.4, 3.8); // Polymorphism data[1] = new Circle(3.9); data[2] = new Parallelogram(3.5, 6.7, 10.2); data[3] = new Rectangle(5.3, 7.2); data[4] = new Circle(4.6); System.out.println("Sum of all Shape2D is "+sum(data)); } } 如果程式語言不支援virtual function的話, 則上面的範例就得寫成下面的形式才行 public class Main { // example for non-virtual function implementation public double sum(Shape2D[] shapes) { double total = 0; for (int i = 0; i < shapes.length; i++) { if (shapes[i] instanceof Rectangle) { total += ((Rectangle)shapes[i]).area(); } else if (shapes[i] instanceof Circle) { total += ((Circle)shapes[i]).area(); } else if (shapes[i] instanceof Parallelogram) { total += ((Parallelogram)shapes[i]).area(); } // modify source code here for new sub classes } return total; } public static void main(String[] argv) { Shape2D[] data; // array of reference to Shape2D data = new Shape2D[5]; // create array object data[0] = new Rectangle(2.4, 3.8); // Polymorphism data[1] = new Circle(3.9); data[2] = new Parallelogram(3.5, 6.7, 10.2); data[3] = new Rectangle(5.3, 7.2); data[4] = new Circle(4.6); System.out.println("Sum of all Shape2D is "+sum(data)); } } final修飾字 final除可用來修飾變數外,也可放在class和object method前面: public final class FinalClass { public final void finalMethod() { } } 放在class前面表示class不可被繼承, 放在object method表示不可被Override。 繼承關係下的Constructor執行順序 先將所有變數設為內定值。對數值型態來說,其值為0; 對reference來說,其值為null; 對 boolean來說,其值為false。 呼叫父類別的constructor。如果子類別Constructor裡沒有指定父類別的Constructor, 則使用父類別沒有參數的Constructor。 執行變數宣告的初始化動作。 執行自己的constructor。 如果要指定父類別其他的constructor,則必須在子類別的constructor的第一行使用關鍵 字super來處理。 class Animal { int aMask = 0x00FF; public Animal() { } public Animal(int mask) { aMask = mask; } } public class Bird extends Animal { int bMask = 0xFF00; int fullMask; public Bird() { // Compiler add super() here fullMask = bMask | aMask; } public Bird(int mask) { /* 若有super,則必須放在第一行,連變數宣告也不能擺在super前面 */ super(mask); fullMask = bMask | aMask; } public static void main(String[] argv) { Bird b = new Bird(); System.out.println(b.fullMask); b = new Bird(0x0011); System.out.println(b.fullMask); } } 當執行new Bird()時,此物件內各個變數的變化如下 步驟 aMask bMask fullMask default 0 0 0 call Bird() 0 0 0 call Animal() 0 0 0 Animal initialize 0x00FF 0 0 execute Animal() 0x00FF 0 0 Bird initialize 0x00FF 0xFF00 0 execute Bird() 0x00FF 0xFF00 0xFFFF 當執行new Bird(0x0011)時,此物件內各個變數的變化如下 步驟 aMask bMask fullMask default 0 0 0 call Bird(0x0011) 0 0 0 call Animal(0x0011) 0 0 0 Animal initialize 0x00FF 0 0 execute Animal(0x0011) 0x0011 0 0 Bird initialize 0x0011 0xFF00 0 execute Bird(0x0011) 0x0011 0xFF00 0xFF11 --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.58.22.74







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Gossiping站內搜尋

TOP