410 likes | 571 Vues
Interfaces and Packages. Lecturer :楊昌樺. Outline. 抽象( Abstract ) 抽象類別( Abstract Classes ) 抽象方法( Abstract Methods ) 巢狀類別( Nested Classes ) 靜態巢狀類別( static nested classes ) 內部類別( inner classes ) Your Turn 介面( Interfaces ) 套件( Packages ) Your Turn. 抽象( Abstract ). 真實世界
E N D
Interfaces and Packages Lecturer:楊昌樺
Outline • 抽象(Abstract) • 抽象類別(Abstract Classes) • 抽象方法(Abstract Methods) • 巢狀類別(Nested Classes) • 靜態巢狀類別(static nested classes) • 內部類別(inner classes) • Your Turn • 介面(Interfaces) • 套件(Packages) • Your Turn
抽象(Abstract) • 真實世界 • 食物為例,應沒見過食物這個東西,一般見到的都是紅蘿蔔、蘋果、巧克力這種真實東西,所以食物可以代表一種抽象概念。 • Java 程式中 • lava.lang.Number 類別代表數字的抽象概念,所以 Number 是一個抽象類別(Abstract Class) • 抽象類別只能被其他類別繼承,不能被實體化 • 如果企圖對 abstract class 進行實體化動作,將會在編譯時期發生錯誤
抽象類別(Abstract Classes) • 定義 • 類別內部有尚未定義實作內容的方法,則此類別必須宣告為 abstract class,該方法需宣告為 abstract method • 宣告 • abstract class Number { … } • 特性 • 宣告為 abstract 的類別無法產生實體。例如,您無法對上述類別做:Number myNumber = new Number(); // 會發生錯誤
抽象方法(Abstract Methods) • 抽象方法(Abstract Methods) • 沒有實作內容的 methods (即沒有 method body) • abstract classes • 至少必須提供一個完整或部分程式碼的 method • 若一個 abstract class 都只有宣告 abstract methods 的話,那就必須改宣告成介面(interface) • 抽象類別主要是用來在繼承上,繼承的 subclass 必須將 abstract classes 中的 abstract methods 實作內容補上
Point Origin; // 重心 moveTo(); // 移動 abstract draw(); // 繪出 抽象類別(Abstract Classes) • 範例: • GraphicsObject 是一個抽象類別,提供所有 subclass 必備的成員變數與 methods GraphicsObject abstract class Rectangle Circle Line
抽象類別(Abstract Classes) public abstract class GraphicsObject { protected Point Origin; public GraphicsObject() { Origin = new Point(0,0); } public void moveTo(int newX, int newY) { Origin.x = newX; Origin.y = newY; } public abstract void draw(); // abstract method protected void finalize() throws Throwable { Origin = null; super.finalize(); } }
抽象類別(Abstract Classes) class Rectangle extends GraphicsObject { public int Length; public int Height; public Rectangle() { Length = 0; Height = 0; } public Rectangle(int Left, int Top, int Len, int High) { Origin.x = Left; Origin.y = Top; Length = Len; Height = High; } public void draw() { // 必須填上 abstract method 的實作內容 System.out.println("Rectangle has been drawn at \n" + "(" + Origin.x + ", " + Origin.y + ") - (" + (Origin.x+Length) + ", " + Origin.y + ")\n" + "(" + Origin.x + ", " + (Origin.y+Height) + ") - (" + (Origin.x+Length) + ", " + (Origin.y+Height) + ")"); } }
抽象類別(Abstract Classes) class Circle extends GraphicsObject { public int Radius; public Circle() { Radius = 0; } public Circle(int a, int b, int r) { Origin.x = a; Origin.y = b; Radius = r; } public void draw() { // 必須填上 abstract method 的實作內容 System.out.println("Circle has been drawn at \n" + "Center: (" + Origin.x + ", " + Origin.y + ")\n" + "Radius: " + Radius); } }
抽象類別(Abstract Classes) class Line extends GraphicsObject { public Point End; public Line() { End = new Point(0,0); } public Line(int a, int b, int c, int d) { Origin.x = a; Origin.y = b; End = new Point(c, d); } public Line(Point p1, Point p2) { Origin.x = p1.x; Origin.y = p1.y; End = new Point(p2.x, p2.y); } public void draw() { // 必須填上 abstract method 的實作內容 System.out.println ("Line: (" + Origin.x + ", " + Origin.y + ") - (" + End.x + ", " + End.y + ")"); } }
抽象類別(Abstract Classes) • 測試主程式:DrawDemo.java public class DrawDemo { public static void main(String[] args){ Rectangle rectObj = new Rectangle(1, 2 ,5 ,5); Circle cirObj = new Circle(1, 1, 5); Line lineObj = new Line(1, 1, 2, 2); rectObj.draw(); cirObj.draw(); lineObj.draw(); } }
巢狀類別(Nested Classes) • Java 中 • 可以將一個類別變成另一個類別的成員 • 如下的程式碼稱為巢狀類別 class EnclosingClass { … class ANestedClass { … } }
巢狀類別(Nested Classes) • 巢狀類別(Nested Classes) • 強制限制住兩個類別之間的關連性 • 使用時機:當某一個類別在另一個類別中才具有意義的時候,如:只有在文字元件(text component)之內,文字游標才具有意義。因此文字游標(巢狀類別)定義於文字元件(類別)之內應是一個很好的選擇。 • 巢狀類別可以存取外層類別的任何成員,即使是宣告成 private 的成員。
巢狀類別(Nested Classes) • 巢狀類別 • 如同其他成員一樣,巢狀類別也可以宣告成 static • 宣告為 static的巢狀類別,稱為靜態巢狀類別(static nested class) • 非 static 的巢狀類別,稱為內部類別(inner class) class EnclosingClass { ... static class StaticNestedClass { ... } class InnerClass { ... } }
巢狀類別(Nested Classes) • 靜態巢狀類別(static nested class) • 與 class variables, class method 一樣都是屬於類別,而非屬於物件 • 與 class method 一樣,在靜態巢狀類別中也不能直接使用實體變數(instance variables) • 反應的是兩個類別之間的關連性 • 宣告 存取範圍 類別特性 繼承宣告 public protected (空白) private static abstract final extends 父類別名稱 implements 父介面名稱 class 類別名稱
巢狀類別(Nested Classes) • 靜態巢狀類別(static nested class) • 使用前不用 new 即可使用。 • 可擁有任何 static 成員。 • 這個Class也是在Load進JVM的記憶體後就存在 • 主類別名稱.內部類別名稱.方法(參數); • 如 Line2.Data.showData("Hi...");
巢狀類別(Nested Classes) • 內部類別(inner class) • 與 instance variables, instance methods 一樣都是屬於物件 • 反應的是兩個類別實體物件之間的關連性 • 宣告 存取範圍 類別特性 繼承宣告 public protected (空白) private extends 父類別名稱 implements 父介面名稱 abstract final class 類別名稱
巢狀類別(Nested Classes) • 內部類別(inner class) • InnerClass 的實體只能存活在 Enclosing Class 物件之內 • InnerClass 可以直接使用 EnclosingClass 物件的實體變數與 methods(包括宣告成 private 的) class EnclosingClass { ... class InnerClass { ... } }
巢狀類別(Nested Classes) • 內部類別(inner class) • 使用前必須先 new 才能使用 • 不可以擁有 static 成員,但可有 static final 成員。 • 可以繼承 static 成員。 • new一個內部物件 • 物件instance.類別名稱 = 物件instance.new 類別名稱(參數); • 如 myLine2.Style = myLine2.new CStyle();
巢狀類別(Nested Classes) • Example: Line2.java import java.lang.Math; public class Line2 { public Point Start; public Point End; public CStyle Style = null; public Line2() { Start = new Point(0,0); End = new Point(0,0); } public Line2(int a, int b, int c, int d) { Start = new Point(a, b); End = new Point(c, d); } public Line2(Point p1, Point p2) { Start = new Point(p1.x, p1.y); End = new Point(p2.x, p2.y); }
巢狀類別(Nested Classes) public class CStyle { int Thickness; int Pattern; int Color; public CStyle() { Thickness = 0; Pattern = 0; Color = 0; } public CStyle(int th, int pt, int cl) { Thickness = th; Pattern = pt; Color = cl; } public String draw() { return "Thickness: " + Thickness + "\nPattern: " + Pattern + "\nColor: " + Color; } }
巢狀類別(Nested Classes) public void CreateStyle(int th, int pt, int cl) { Style = new CStyle(th, pt, cl); } public void draw() { System.out.println ("Line: (" + Start.x + ", " + Start.y + ") - (" + End.x + ", " + End.y + ")"); } public double area() { return Math.sqrt(Math.pow(End.x - Start.x,2) + Math.pow(End.y - Start.y,2)); } protected void finalize() throws Throwable { Start = null; End = null; super.finalize(); } }
巢狀類別(Nested Classes) • Line2 的測試主程式:DrawLine2.java public class DrawLine2 { public static void main(String[] args) { Line MyLine = new Line(1,1,5,5); MyLine.draw(); System.out.println("Length = " + MyLine.area()); MyLine.CreateStyle(3,3,3); System.out.println(MyLine.Style.draw()); } }
Your Turn • 假設給定以下類別:Parcel.java,試著在此類別中寫一個 main() 來測試其中所有巢狀類別的方法。 public class Parcel { class Contents { private int i = 11; public int value() { return i; } } class Destination { private String label; Destination(String whereTo) { label = whereTo; } String readLabel() { return label; } } static class Data { static void showData(String data){ System.out.println(data); } } }
介面(Interface) • 定義 • 一段只有常數與函式宣告,但沒有函式實作的程式碼。 • 宣告 • [public] interface 介面名稱 [extends 父介面名稱] • 作用 • 讓某個功能,不論由誰實作,都能夠有相同的函式名稱,傳入值,傳出值,與存取範圍。
介面(Interface) • 定義介面 public interface Stockwatcher { final String sunTicker = “SUNW”; final String oracleTicker = “ORCL”; final String ciscoTicker = “CSCO”; void valueChanged(String tickerSymbol, double newValue); … }
介面(Interface) • 介面(interface)與抽象類別(abstract class) • 介面裡不能實作任何 methods;不過,abstract class 可以 • 一個類別可以同時實作多個介面;但一個類別只能有一個 superclass(Java 不支援多重繼承) • 介面不屬於類別階層架構的一份子。毫不相干的類別,也可以實作相同介面 • 因為多重繼承會有問題,但實際上又有多重繼承的需要,所以發明了 interface,作為折衷的替代方案。
介面(Interface) • 注意事項 • 如果某介面繼承另一個介面,則 subclass 能從 superclass 繼承到的只有常數與函式宣告而已。 • 介面一旦公佈出去,開始供大家使用後,就請盡量不要更改。因為一旦更改,那些已經使用此介面的程式會因無法實作新功能,而不能執行。 • 如果真要更改,請宣告新介面,其它人就可以決定要實作一個介面或兩個介面都實作。 • 優點 • 快速知道如何使用此class,省去閱讀大量文件之時間
Point Origin; // 重心 moveTo(); // 移動 abstract draw(); // 繪出 Point Origin; moveTo(); abstract draw(); Point Origin; moveTo(); abstract draw(); Point Origin; moveTo(); abstract draw(); void fillColor (int Color); double getArea(); 介面(Interface) • 範例: GraphicsObject Rectangle Circle Line Paintable
介面(Interface) • 範例:Paintable.java public interface Paintable { public void fillColor(String Color); public double getArea(); }
介面(Interface) • 範例:Rectangle2.java public class Rectangle2 extends GraphicsObject implements Paintable { public int Length; public int Height; public Rectangle2() { Length = 0; Height = 0; } public Rectangle2(int Left, int Top, int Len, int High) { Origin.x = Left; Origin.y = Top; Length = Len; Height = High; }
介面(Interface) public void draw() { System.out.println("Rectangle has been drawn at \n" + "(" + Origin.x + ", " + Origin.y + ") - (" + (Origin.x+Length) + ", " + Origin.y + ")\n" + "(" + Origin.x + ", " + (Origin.y+Height) + ") - (" + (Origin.x+Length) + ", " + (Origin.y+Height) + ")"); } public void fillColor(String Color) { System.out.println("Rectangle has been filled with " + Color); } public double getArea() { return Length * Height; } }
套件(Package) • 定義 • 性質相似之類別的集合 • 宣告套件的方法 • 在原始檔案的第一行寫下:package 套件名稱; • 套件示意圖 Graphics 套件 XXX.java YYY.java ZZZ.java package Graphics; Class XXX { } package Graphics; Class YYY { } package Graphics; Class ZZZ { }
套件(Package) • 套件目的 • 防止兩位程式師取了相同的類別名稱 • 套件命名習慣 • 將公司的網際網路名稱倒過來寫 • 範例:package tw.com.pcschool.Graphics • 有時會再加上部門名稱 • 範例:package tw.com.pcschool.rd.Graphics
套件(Package) • 在 Java 中規定,.class 檔案真正存在的地方必須與套件的命名結構相對應 Point.java Point.class package tw.com.pcschool.Graphics; class Point { ….. } tw com pcschool Graphics Point.class
套件(Package) • package 與目錄結構 • 所有屬於 packagename類別庫的 .class 檔案都必須儲存在 packagename資料夾下 • packagename必須唯一,類別庫名稱可使用句點分隔不同層次的資料夾名稱 • 例: package tw.com.pcschool.Graphics package tw.com.pcschool.rd.Graphics • 使用 javac 之參數 • 語法:javac –classpath user-class-path –d des-path xxx.java • -classpath:指定使用者自訂類別路徑,至存放類別目錄的上一層 • -d:指定編譯完成之 .class 檔案產生路徑 • 若指定路徑中的名稱包含空白,必須使用雙引號括起來
套件(Package) • Source 與 Class 檔的管理 • Source 檔與 Class 不一定要放在同一個目錄下 • 將 source 與 class 檔分開放
註:套件(Package)Command版 • 編譯時能夠抓到我們自訂的套件,要用 classpath 參數告訴 javac 到哪裡去找我們要的套件 • 在 javac 後方直接用 –classpath 參數javac –classpath .;c:\jdk1.3\lib;c:\mylib\tw\com \pcschool\Graphics Point.java • 使用 jar 壓縮檔案 • 語法:jar cvf jar-file-name –C directory-path/ . • 在 cmd 視窗中,輸入 jar,並參閱其說明 • 使用類別庫 • 語法:java –classpath .;user-class-pathmain-class • 用分號「;」區隔多個類別庫 • 類別庫可為目錄路徑、zip 檔案或 jar 檔案 • 目錄擺放結構一定要正確!
用eclipse作套件jar檔 使用Fat Jar的plug-in 將plug-in目錄放在eclipse目錄 可在命令列執行eclipse –clean讓plug-in反映上去 成功後以後Project按右鍵會多Build Fat Jar選項 選擇Finish即可 別的專案創造時選Library 別的程式import其class
Your Turn • 製作套件及使用練習: • 試著將此課堂中所講解的程式碼:GraphicsObject.java、Point.java、Circle.java、Rectangle.java 以及 Line.java 全部都 整合到 tw.com.Graphics 套件中 • 最前面加 package tw.com.Graphics; • 因為要跨專案,所以別程式用到的Point, Circle, Rectangle等類別要變成public • 創造新專案裡面放 DrawDemo 程式 • 一開始要import tw.com.Graphics.*; • 確認可以正確執行 DrawDemo裡面的main程式