450 likes | 608 Views
繼承 (inheritance). 繼承是一種讓軟體可重復利用的最佳方法 , 除了父類別中的 private 屬性與方法 , 全都可以被子類別所繼承 . 繼承之後子類別可以增加一些父類別所沒有的新功能 , 或者是覆寫所繼承到父類別中不須要的 ( 或甚至是不對的 ) 方法 。 子類別所代表的物件類型通常要比父類別來得具體些 , 因此也代表較少量的物件 。 子類別的物件通常可以被視為是一種父類別型別的物件. 類別的繼承 (inheritance). Java 在繼承的機制上是採用「 單一繼承 」的方式,也就是說,一個類別最多只能直接繼承自另一個類別。
E N D
繼承(inheritance) 繼承是一種讓軟體可重復利用的最佳方法,除了父類別中的private屬性與方法,全都可以被子類別所繼承. • 繼承之後子類別可以增加一些父類別所沒有的新功能, 或者是覆寫所繼承到父類別中不須要的(或甚至是不對的)方法。 • 子類別所代表的物件類型通常要比父類別來得具體些, 因此也代表較少量的物件。 • 子類別的物件通常可以被視為是一種父類別型別的物件
類別的繼承 (inheritance) Java在繼承的機制上是採用「單一繼承」的方式,也就是說,一個類別最多只能直接繼承自另一個類別。 • 如果類別沒有明確的指定其父類別為何,在編譯時,類別都會自動繼承自Object類別。 • 繼承需要使用「extends」關鍵字,語法如下: [modifier]* class ClassName extends SuperClassName { …….. }
public, private, protected • 我們用import指令,引入進來不同程式的類別 • 在同一目錄中的類別不需用import指令,便能引入進來使用 在同一個目錄中JAVA程式檔案 在不同一個目錄中JAVA程式檔案
extends • 基礎類別又稱『父類別』、衍生類別又稱『子類別』 • 除了private的成員以外, ClassA的所有成員均會被 ClassB 所繼承 • Java 中的『繼承』語法 ClassA 基礎類別 (base class) 繼承 ClassB 衍生類別 (derived class)
package ... Class-A1 Class-A2 Class-A3 繼承 Class-B1 父類別的 protected 成員 • 父類別的 protected 成員, 可以被『父類別中的方法』、『子類別中的方法』、『同一包裹(目錄)中的類別』所存取 可存取 Class-A1 中的 protected 成員的類別有: (1) Class-A1 中的方法 (2) Class-A1 的子類別(Class-B1)中的方法 (3) 與 Class-A1 同 package 的所有類別(Class-A2, Class-A3)中的方法
例子: 繼承前一章的Std_dat類別, // 使此檔與 Std_dat.java 同一目錄(檔案夾) public class newStudent extends Std_dat { int Chi; public newStudent() { super(); }//呼叫父類別建構子的敘述寫在子類別建構子的第一行 public void setChi(int c) //設定國文成績 { Chi = c; } public int getChi() //取得國文成績 { return Chi; } public int getAvg() //取得三科平均 { return( super.getAvg() *2+ Chi )/3; } } /* 這個繼承Std_dat類別的newStudent類別中,另外新增1. 一個新的變數Ch1,2.method setChi()和3.getChi(), 另外還override了Student類別中的getAvg method。 */
super • super的使用 • 「super」會參考到目前類別的父類別,這裡所謂的父類別是指宣告類別時,「extends」關鍵字之後的類別。使用的語法如下: • 呼叫父類別建構子(super()) 的敘述寫在子類別建構子的第一行,否則,編譯時會產生錯誤。 • super.成員;
Super使用例 • 若在子類別中有與父類別中相同成員名稱, 則子類別可以用 super 關鍵字來存取父類別中的成員
Super()使用例 • 當父類別中有多個建構函數時,則必須在子類別中使用 super() 命令,來決定執行哪一個建構函數。 • 預設值為呼叫父類別的建構子 super()通常會被放在子類別的建構子的第一行 (為什麼?)
final • final表示此類別,method或屬性是不能被更改的,而且也不能再被繼承。這樣的好處是防此已經寫好的method 被繼承的子類別改寫掉。 • final修飾子可以套用於類別、屬性或是方法上。 • 如果屬性設定為「final」,程式應在宣告時同時指定「final」屬性的值; • final屬性的值一旦設定之後,屬性的值就不可以再更改了。 • 如果將物件變數設定為「final」,程式中也不能再改變該物件屬性的參考,但您可以改變該物件屬性所指到的資料內容。 • 如果類別使用了final修飾子,則該類無法再被繼承 。
Final 變數 final屬性(Constant), 亦即內容不會被改變的屬性,請參考 Circle 類別的PI。 final 變數必須在宣告時便設定其值, 而且不能改變其內容
final類別與final方法 • 屬性前加上final: 其內容不能被改變 • 方法前加上final: 其內容不能在子類別中被覆寫 • 類別前加上final: 此類別不能再被繼承 此類別不能再被繼承 此變數內容不能被改變 此方法不能在子類別中被覆寫
多型(polymorphism) • 又稱為同名異式。(overload, override)就是多型的一種應用。。 • 應用多型功能就可以提供統一的呼叫介面,程式會自動根據不同的需求(參數),執行不同方法的程式碼。
Overload多形 • Overload:是指在同一個類別中,有相同名稱的method,但傳入的參數不同。或者是說子類別中有跟被繼承的類別有相同名稱的method,但是參數不同。而當我們在使用這樣的方法時,依所傳入的參數不同,而叫用不同的method。 • (overload)不可設計有相同名稱與相同的傳入參數,但不同傳回值的method 回深入Java物件導向
Override 多形 • 在子類別中如果當method名稱和傳入參數與父類別的method都一樣時,那就叫做override,程式在執行時會採用子類別所定義出的新的method。請參考 Circle,CCircle 類別的toString()函數。
在Java裡面有三種class:標準class、abstract class、interface。 • 標準class是指那些每一個方法都有實作(有完整的寫出函式內容的class). • abstract class則是:class裡面有一部份方法只宣告了名稱,卻沒有實作內容!另一部份方法宣告了名稱也有實作內容 • interface裡面則是:class裡面所有方法完全沒有實作,只是宣告了方法名稱. • 要注意的是,對於後面兩種class來說,都不能用來產生object,一定要用另外的子類別來繼承之後,並且override那些沒有被實作的方法,才能用來產生object。
抽象類別 抽象類別 Shape 繼 承 繼 承 繼 承 Triangle Circle Rectangle abstract是override的預備概念 • abstract類別 • 目的: 提供一個『父類別』, 讓其子類別可繼承它屬性與方法並override之 • abstract類別在於搜集子類別中相同的屬性與方法名稱而成為一種可以讓很多類別繼承的類別。(例如計算各種形狀的面積的方法皆稱為area() ,但其計算的公式皆不相同 • 範例:
abstract類別的變數 • 抽象類別的變數可以指向子類別之物件 • abstract修飾子只可以套用於類別及函式上。 • 宣告為「abstract」的類別只能用來被繼承,而不能夠被實體化。 • 如果類別中的成員方法使用了「abstract」修飾子,該成員方法只有名稱、參數內容和回傳型別的定義,不能有實作的部份。 • 在類別中,只要有一個成員方法使用了「abstract」修飾子,則該類別也必需使用「abstract」修飾子。但該類別中並不需要將所有的成員方法都宣告成「abstract」,abstract類別中也可以宣告資料成員。
abstract方法 • 如果子類別將abstract父類別的方法全部override,那麼子類別就可以被實體化。 • abstract方法不可以使用static、private以及final等關鍵字。 回深入Java物件導向
abstract方法範例 • 範例: 抽象方法
應用抽象類別的程式碼範例(Cshap.java): abstract class CShape // 定義抽象類別CShape { String color; public void setColor (String c) { color=c; } public String getColor() { return color; } abstract public double area(); abstract public String toString(); // 只宣告toString(),但沒有定義處理方法 } /*讓第八章的 class Circle 與 class Rectangle 都繼承 class CShap 將其class 改寫如下: class Circle extends CShape class Rectangle extends CShape 藉由抽象類別,在class Rectangle,class Circle 類別中可以實作toString(),area()方法 */
(8-0章 p.16) class Circle 的 toString()可override如下 public String toString() { return "(x),(y),radius,area,color="+center.toString()+","+ r +","+area()+","+color; } (8-0章 p.13)class Rectangle 的 toString()可override如下: public void toString() { return "(L,W),area,color =("+ length+","+width+")" +","+area()+","+color; }
class Circle extends CShape { final static double PI=3.14159; //靜態常數 int x; int y; int r;//radius public Circle() {}//(constructor) public void setX( int x) { this.x=x;} public void setY( int y) { this.y=y; } public void setR( int r) { this.r = r; } public int getX() { return x;} public int getY() { return y;} public int getR() { return r; } public double area() { return PI*r*r; } public String toString() { return "(x,y)=("+x+","+y+"),r="+r +",a="+this.area(); } }
class Rectangle extends CShape { int x; int y; int l; int w; //instance私有成員 public Rectangle(){}//建構函數 public void setX (int x) { this.x=x; } public void setY (int y) { this.y=y; } public void setL (int l) { this.l=l; } public void setW (int w) { this.w=w; } public int getX() { return x;} //instance方法 public int getY() { return y; } public int getL() { return l; } public int getW() { return w; } public double area() { return (l*w*1.0); } public String toString() { return "(x,y)=("+x+","+y+")"+",(L,W)=("+l+","+w+"),area ="+ area(); } }
Abstract.java // 使此檔與 CShape.java Circle.java Rectangle.java 存放同一目錄(檔案夾) import java.lang.String; public class Abstract { public static void main(String argv[]) { CShape S; Rectangle Rc=new Rectangle(); Rc.setX(20); Rc.setY(30); Rc.setL(10); Rc.setW(50); Circle Ci=new Circle(); Ci.setX(20); Ci.setY(30); Ci.setR(40); Ci.setColor("r "); Rc.setColor("B "); System.out.println(Rc.toString()); System.out.println(Rc.getColor()); System.out.println(Ci.toString()); System.out.println(Ci.getColor()); S=Rc; System.out.println(S.toString()); //可以透過abstract型態的變數來存取物件 S=Ci; System.out.println(S.toString()); } }
抽象類別 String Name String getName() void setName() abstract int Salary() Employee 繼 承 繼 承 繼 承 類別 類別 類別 Boss Manager Engineer int Salary() int Salary() int Salary() 多型 • 多形(Polymorphism) • 用例子來解釋
繼 承 override 多型 • 多形(Polymorphism)
多型 • 多形(Polymorphism)
多型 • 多形的真正威力 • 可以把繼承於同一個抽象類別的子類別物件轉型為其父類別, 並以陣列的方式來存取
介面(interface)是一種與抽象類別相似的結構 • 與抽象類別的差異為: • 「介面類別」主要是用來定義一群行為動作的規格,它並不能直接用來產生物件 • Java 不提供類別多重繼承 (multiple inheritance),但提供介面(interface)多重繼承的機制。 • 介面中的資料成員都必須設定初值常數。 • Interface中所有方法只能包含public,不可被定義成private或其他修飾元。 • interface 中所有的方法均為abstract • interface乍看之下跟abstract類別有點相似,在abstract類別裡面至少會有一個method實作,而在interface中完全只有定義abstract method和常數,所以說interface是一個完全的abstract類別。
抽象類別 介面 改成 介面 interface 沒有建構子也不可被實體化
改成 實作 extends 與 implements • 實作(implement) • 若抽象類別被改寫為介面(interface), 則其子類別可以改成 impleaments 來繼承之
implement • 實作(implement)的語法如下: class classname implements interface_name1, interface_name2,… • 這裡有一點要注意的是,因為interface裡所定義的method都是抽象的,所以要實作它的類別,必須所有的method都要實作。下面我們就來看看如何實作一個interface:
介面與多重繼承: • 多重繼承(Multiple Inheritance)是指繼承兩個以上的類別 • Java利用interface來達成多重繼承(這樣可以使這個class擁有很多的功能)。 • 當一個class繼承了一個abstract class之後,就不能再繼承任何一個class了! • 但是interface則不同,一個class可以實作(implements) 一堆interface,這樣就可以達到部分多重繼承的效果!
介面乍看之下跟抽象類別有點相似,在抽象類別裡面至少會有一個抽象method,而在介面中完全只有定義method和常數,所以說介面是一個完全的抽象類別。介面乍看之下跟抽象類別有點相似,在抽象類別裡面至少會有一個抽象method,而在介面中完全只有定義method和常數,所以說介面是一個完全的抽象類別。 //--------Picture.java import java.awt.*; interface Picture { abstract public void draw(Graphics g); } interface CtoString { abstract public double area(); abstract public String toString(); }
Line.java import java.awt.*; public class Line implements Picture,CtoString { int x1,x2,y1,y2; public Line(int x1, int x2, int y1, int y2) { this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2; } public void draw(Graphics g) { g.drawLine(x1,x2,y1,y2); } public double area() { return 0.0; } public String toString() { return "(x1,y1,x2,y2)("+x1+","+y1+","+x2+","+y2+")"; } public static void main(String argv[]) { Line l=new Line(10,20,30,40); System.out.println(l.toString()); } }
使用 super() 範例【CCircle 含有色彩的圓】 類別中的靜態變數&建構函數例: // 使此檔與Circle.java,同一目錄(檔案夾) import java.awt.*; public class CCircle extends Circle implements Picture { private String color=new String(); public CCircle(int x,int y,int r) { super(); super.setX(x); super.setY(y); super.setR(r); } public void draw(Graphics g) { g.drawOval(x,y,r,r); } public void setColor(String c) { this.color=c; } public String getColor() { return color; } public String toString() { return super.toString() +",color="+ color; } public static void main(String argv[]) { CCircle cc=new CCircle(20,30,40); cc.setColor("red"); System.out.println(cc.toString()); } }
CRectangle.java import java.awt.*; public class CRectangle extends Rectangle implements Picture { private String color; public CRectangle() // 沒有引數的建構元 { super();} public CRectangle(int x, int y, int l, int w) { super.setX(x); super.setY(y); super.setL(l); super.setW(w); } public void draw(Graphics g) { g.drawRect(x,y,l,w); } public void setColor(String c) { this.color=c; } public String getColor() { return color; } public String toString() { return super.toString() +",color="+ color; } public static void main(String argv[]) { CRectangle crc=new CRectangle(12,34,50,34); crc.setColor("red"); System.out.println(crc.toString()); } }
Shape.java // 使此檔與CCircle.java, Line.java, Picture.java同一目錄(檔案夾) import java.awt.*; import java.applet.*; public class Shape extends Applet { CCircle c; Line l; public void init() { c=new CCircle(30,100,20); l=new Line(100,50,300,50); } public void paint(Graphics g) { g.drawString(c.toString(),50,10); g.drawString(l.toString(),50,30); l.draw(g); c.draw(g); for (int i=20;i<200;i+=30) { c.setR(i); c.draw(g); } } }
繼承作業:1 • 請設計一 個人資料 類別 Person,包含 A.兩個字串型態資料欄: 1.姓名(name)及2.血型(blood),B.包含5個方法:1.設定姓名 setName()、2.設定血型 setBlood()、//設定血型 時只有 O,A,B,AB 能進入 3.取得姓名 getName()、4.取得血型 getBlood()、 5.顯示物件本身 toString(), C.包含兩個建構子:1.Person()、及 2.Person(String name, String blood)。 • 然後設計一個main方法,已知姓名 為 “張三”、血型為 “B”,使用 toString() 方法將物件顯示出來。 • 建立一個 Person 類別的物件 p 如下: Person p = new Person("李四", "AB"); 然後使用 toString() 方法將姓名,血型顯示出來。
//============ Person.java ==================Example public class Person { String name; String blood; Person() {} Person(String name, String blood) { ... //您要填入的程式碼 } public void setName(String n) { ... //您要填入的程式碼 } public void setBlood(String b) { ... //您要填入的程式碼 } public String getName() { ... //您要填入的程式碼 } public String getBlood() { ... //您要填入的程式碼 } public String toString() { ... //您要填入的程式碼 } public static void main(String args[]) { Person p=new Person("張三", "B"); System.out.println(p.toString()); } }
2。建立一個 Person2 類別繼承Person,包含變數:姓名(name)、血型(blood)、體 重(weight)、身高(height)。 方法: 顯示物件本身 toString()、 設定重量 setWeight()、// 設定身高 setHeight()。、 取得重量 getWeight()、 取得身高 getHeight()。 建構子 Person2()、 建構子 Person2(String name, String blood, int weight, int height)。 • 然後設計一個main方法,已知姓名為 "張三"、血型為 "B"、體重 76、身 高 178,使用 toString() 方法將物件顯示出來。
3。設計一個 Person3 類別,繼承 Person2 類別變數及方法之外,增加變 數電話 telephone,增加 setTelephone(),getTelephone().兩個建構子Person3() 及 Person3(String name,String blood, int weight, int height, int telephone)。顯示物件本身 toString()、 • 然後設計一個main方法,已知姓名為 "張三" 、血型為 "B"、體重 76、身高 178、電話 7317777,使 用 toString() 方法將物件顯示出來。
作業:有一abstract類別Shape如下,將以下的作業1,2加上適當的建構函數與get,set 方法完成其類別的設計,再用一Test.java程式測式此二類別. 抽象類別 Shape 宣告如下。perimeter() 為計算周長的方法,getType() 為抽象方法,傳回型態名稱字串。 public abstract class Shape { public double perimeter() { return 0.0; }; public abstract String getType() ; } 1。請設計一個類別 ShapeR extends Shape 的物件方法顯示圖形型態及矩形周長 。 public class ShapeR extends Shape { private double w, h; public ShapeR() { w=0; h=0; } public ShapeR(double w, double h) { this.w=w; this.h=h; } public double perimeter() { return (w+h)*2; }; public String getType() { return "矩形"; } } 2。請設計一個類別 Circle 使用 Shape 的物件方法顯示圖形型態及圓形周長 。 public class Circle extends Shape { private double r; public Circle() { r=0; } public Circle(double r) { this.r=r; } public double perimeter() { return 2.0*Math.PI*r; }; public String getType() { return "圓形"; } }
作業 import java.awt.*; interface Picture { abstract public void draw(Graphics g); } interface Shape // 定義抽象類別CShape { abstract public double area(); abstract public String toString(); } 寫一applet程式建立一Rectangle類別,實作以上 Picture,Shape 介面,在網頁上相同左上角位置繪出一個矩形,並顯示其面積, 長(l), 寬(w) Rectangle 中的屬性有(1)Rectangle 左上角的點座標(2)長(l), 寬(w)