Java 程式設計()  第 七章 類別與物件產生  上一頁    下一頁

 

7-3 物件的產生

內容:

  • 7-3-1 物件產生敘述 - new()

  • 7-3-2 範例研討:規劃通用型人事資料

    • (A) 程式功能

    • (B) 製作技巧研討

    • (C) 員工物件類別 - Employess.class

    • (D) 程式範例

    • (E) 直接存取隱藏變數

7-3-1 物件產生敘述 – new()

設計好類別藍圖之後,接下來必須考慮如何將類別實現成為一個可執行運作的『物件』。像是蓋房子一樣,同一張建築藍圖可能因所需的人不同、所蓋的地理位不同、所建設的時間不同等等不同因素,即使照圖蓋出外觀一樣的房子,內裝樣式卻可能出現很大的差別。由此可見,由同一份類別所產生的物件之間,也會因所面臨的狀況不同,產生外觀相同,內部大異其趣的物件。因此,任一時機內,由類別產生一個物件,只不過當時狀況的一個『驗例』(Instance)而已,由類別產生物件的過程稱為『驗例化』(Instantiate,某些地方稱為物件化)。利用 new () 函數呼叫,由類別產生一個物件,語法如下:

 

物件產生語法

      

物件宣告

class_name object_name;

Employee Liu;

物件產生

object_name = new class_name();

Liu = new Employee();

物件宣告並產生

class_name object1 = new class_name();

Employee Cheng = new Employee()

物件內變數

object_name.variable_name

Cheng.name

物件內方法

object_name.method_name

Cheng.setID()

重點說明如下:

(1) class_name object_name Employee Liu):宣告某一資料型態為 class_name 類別(如 Employee)的物件,其名稱為 object_name(如Liu其實宣告類別的語法,與宣告基本資料型態變數的方法很類似,如 int k 語句。

(2) object_name = new class_name() Liu = new Employee()):產生一個 class_name 型態(如 Employee)的物件,並填入 Liu 物件內。像是整數宣告int k = 10

(3) 上述兩個敘述可整合一個敘述達成,則為 class_name object1 = new class_name()譬如 Employee Cheng = new Employee ()

上述範例中,Employee 為事先製作好的類別,並經過編譯成 Employee.classBytecode,中介程式);而且須與原程式儲存放於同一目錄底下,否則必須利用 classpath 變數(第一章有設定 classpath 說明),標明 Employee.class 的所在位置。利用 new 產生的物件其特性如下:

(1) 變數成員表示:經由類別產生的物件,該物件內的變數成員也繼承了原類別所規劃的屬性,可能是 publicprivate protected 的存取限制。變數成員的表示方法為:

   『object_name.variable_name』( Cheng.name

(2) 方法成員表示:物件內的方法成員承襲了原類別所規劃的屬性,可能是 public private;方法成員表示為:

  『object_name.method_name』( Cheng.setID()

7-3-2 範例研討:規劃通用型人事資料

A程式功能:Ex7_1.javaEmployee.java

展鵬網路行銷公司需要一套較完整的人事資訊系統,該系統允許編輯員工資料,每一員工的描述屬性有:

(1) 員工代號(ID):整數。必須高於 1000,且低於 5000

(2) 姓名(name):字串。

(3) 部門(depart):字串。

(4) 底薪(payment):整數。必須高於最低薪資 15800 元。

(5) 加班時數(extra):整數。最高 45 小時。

請先建立一只雛型程式,允許輸入員工資料,如輸入資料不符規定,則不予輸入並顯示錯誤原因。輸入完畢後印出該員工的薪資表,其中加班費計算方式為每小時 = (底薪 / (30 * 8)) * 1.5。期望操作介面如下:

(1) 編譯後,正常執行如下:

D:\Java2_book\chap7\Ex7_1>javac Employee.java   【編譯 Employee 類別】

D:\Java2_book\chap7\Ex7_1>javac Ex7_1.java      【編譯 Ex7_1 類別】

 

D:\Java2_book\chap7\Ex7_1>dir/b        Employee.class 須於同一目錄】

Employee.class

Employee.java

Ex7_1.class

Ex7_1.java

 

D:\Java2_book\chap7\Ex7_1>java Ex7_1

** 展鵬資訊 建立員工資料 **

請輸入 員工姓名 =>張大得

請輸入員工部門 = >資訊部

請輸入員工代號 =>1201

請輸入員工底薪 =>45000

請輸入員工加班時數 =>23

**** 列印員工薪資表 *****

代號   姓名     部門    本月薪資

1201    張大得  資訊部  49301

(2) 如果員工編號不在 1000~5000 範圍內,系統會拒絕操作並離開,如下:

D:\Java2_book\chap7\Ex7_1>java Ex7_1

** 展鵬資訊 建立員工資料 **

請輸入 員工姓名 =>張第一

請輸入員工部門 = >管理部

請輸入員工代號 =>134

1000 <員工代號 < 5000 範圍 !!

程式停止運作

(3) 如果員工薪資低於 15800,則系統會拒絕操作並離開,如下:

D:\Java2_book\chap7\Ex7_1>java Ex7_1

** 展鵬資訊 建立員工資料 **

請輸入 員工姓名 =>林添財

請輸入員工部門 = >管理部

請輸入員工代號 =>1203

請輸入員工底薪 =>12000

底薪不可低於 15800

程式停止運作

(4) 如果員工加班時數超過 45 小時,則系統會拒絕操作並離開,如下:

D:\Java2_book\chap7\Ex7_1>java Ex7_1

** 展鵬資訊 建立員工資料 **

請輸入 員工姓名 =>林森林

請輸入員工部門 = >製造部

請輸入員工代號 =>1208

請輸入員工底薪 =>24000

請輸入員工加班時數 =>56

勞基法規定加班時數不可超過 45 小時

程式停止運轉

B製作技巧研討:

物件的簡單應用,如同傳統語言的『結構變數』一樣,大多運用於描述環境的事實現象(或稱 Entity)。但物件不僅被動的描述 Entity 的屬性外,如果給予適當的處理,它可主動判斷『事項』是否已超過真實現象。以電子化人事系統為例,對於公司內員工薪資或工時計算大多不可以違反『勞工法』規定,譬如員工代號大多有一定格式、勞工最低薪資、每月最高超工時數、等等。

我們相信公司裡某些規定是適合所有員工,也就是員工資料制定完成之後,大多可以適用所有部門員工。因此,吾人依照展鵬公司的需求,製作了如圖 7-5 Employee 類別(Employee.java),其他應用系統也可直接引用,如此則可以整合公司內的員工資料。圖 7-5 是由 Employee 類別產生 worker sales 員工物件的範例。設計完成員工資料類別之後,再編寫建立員工資料程式(Ex7_1.java)就不會困難了。

7-5 員工資料的物件範例

C 員工物件 - Employee.class

吾人利用 Employee.java 建構宣告員工物件的類別(Employee.class);該類別內包含 5 個變數成員(其中 3 個是隱藏式變數),與 6 個存取隱藏變數的方法成員,然而它們即是該類別的輸入/輸出埠口。從外觀來看,Employee.class 抽象功能如圖 7-6 所示。各項功能如下說明:

(1) 屬於輸入埠口:

(a) int setID(int i):設定員工代號,如 i 介於 1000~5000 之間則執行正常返回 1;否則返回 0。該方法是設定物件內變數成員,屬於輸入埠口之一。

(b) int setPayment(int pay):設定員工底薪,如 pay 大於 15800,則執行正常並回傳 1;否則回傳 0,表示拒絕操作。屬於物件的輸入埠口之一。

(c) int setExtra(int ex):設定員工加班時數,如 ex 小於 45 則執行正常並回傳 1;否則回傳 0。屬輸入埠口之一。

7-6 Employee.class 類別架構

(2) 屬於輸出埠口:

(a) int getID():取得員工代號。輸出埠口之一。

(b) int getPayment():取得員工底薪。輸出埠口之一。

(c) int getExtra():取得員工加班時數。輸出埠口之一。

(d) name:儲存員工姓名的變數,可任意存取。

(e) depart:儲存服務部門的變數,可任意存取。

(3) 屬於物件變數:

(a) 公開變數:有 name(員工姓名) depart(服務部門) 2 個變數,外部程式可以直接存取(讀或寫)

(b) 私有變數:有 ID(員工編號)payment(底薪) extra(加班時數) 3 個變數,外部程式不可以直接存取,必須透過輸入/輸出埠口存取,如 setID()getID()、、、等物件方法。

(4) Employee.java 程式範例,如下

7-7 Employee.java 程式架構

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

//Employee.java

 

class Employee {

 

    /* 宣告物件成員 ***/

    private int ID;            // 員工代號, 介於 1000~5000

    String name;               // 員工姓名

    String depart;             // 所屬部門

    private int payment;       //     > 15800

    private int extra;         // 加班時數 < 45

 

    /*** 宣告物件方法 ***/

    int setID(int i) {      // 設定員工代號方法, 1: 正常, 0: 錯誤

         if((i>1000) && (i <5000)) {

              ID = i;

              return 1;

         }

         else {

              System.out.printf(" 1000 <員工代號 < 5000 範圍 !!\n");

              return 0;

        }

    }

    int getID() {            // 讀取員工代號方法

         return ID;

    }

    int setPayment(int pay) {   //設定底薪方法, 1: 正常, 0: 錯誤

         if (pay < 15800) {

             System.out.printf("底薪不可低於 15800 \n");

             return 0;

         }

         else {

             payment = pay;

             return 1;

         }

     }

     int getPayment() {      // 讀取底薪方法

         return payment;

     }

     int setExtra(int ex) {    // 設定加班時數方法, 1: 正常, 0: 錯誤

         if (ex > 45) {

             System.out.printf("加班時數不可超過 45 小時\n");

             return 0;

         }

         else {

             extra = ex;

             return 1;

         }

     }

     int getExtra() {        // 取得加班時數方法

         return extra;

     }

}

程式重點說明:

(1) 6~10 :宣告類別的變數成員,並指定其相關屬性(如 private)。

(2) 14~23 :『int setID(int i) { ..}』。宣告 setID() 方法成員,該方法被呼叫時,會攜帶參數 i,如果該參數介於 1000 5000 之間,則這定員工代號,並回傳一個整數 1;否則拒絕設定,亦回傳 0

(3) 24~26 :『int getID() {…}』。宣告 getID() 方法成員,功能是回傳員工代號(ID)。

(4) 27~37 :『int setPayment(int pay) { ..}』。功能是設定員工底薪的方法成員;當引數(pay)底薪低於 15800 元,該方法會拒絕輸入,並回傳一個整數 0;否則回傳整數 1

(5) 38~40 :『int getPayment() {…}』。 讀取員工底薪的方法成員。

(6) 41~50 :『int setExtra(int ex) { ..}』。輸入員工加班時數的方法成員;當引數超過 45 時,會拒絕輸入並回傳 0;否則回傳 1

(7) 51~53 :『int getExtra() { … }』。讀取員工加班時數的方法成員。

D主程式範例 - Ex7_1.java

7-8 Ex7_1.java 程式架構

製作完成 Employee 類別之後,吾人再編寫一主程式,引用該類別來產生工作員(worker)。針對 worker 物件輸入與輸出資料,證實 Employee 類別所提供的方法與變數成員是否能滿足所需。

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

//Ex7_1.java

/* 請建立一套人事資訊系統,該系統允許員工輸入資料,並印出該員工的薪資表 */

 

import java.util.*;

// Employee.class 於同一目錄下

public class Ex7_1 {

    public static void main(String args[]) {

         Scanner keyin = new Scanner(System.in);

         Employee worker = new Employee();

         int id, pay, ex, pay1;

        

         System.out.printf("** 展鵬資訊 建立員工資料 **\n");

         System.out.printf("請輸入 員工姓名 =>");

         worker.name = keyin.nextLine();

         System.out.printf("請輸入員工部門 = >");

         worker.depart = keyin.nextLine();

 

         System.out.printf("請輸入員工代號 =>");

         id = keyin.nextInt();

         keyin.nextLine();

         if (worker.setID(id)==0) {

              System.out.printf("程式停止運作 \n");

              return;

         }

 

         System.out.printf("請輸入員工底薪 =>");

         pay = keyin.nextInt();

         keyin.nextLine();

         if (worker.setPayment(pay) == 0) {      // 判斷是否正常設定

              System.out.printf("程式停止運作 \n");

              return;

         }

 

         System.out.printf("請輸入員工加班時數 =>"); 

         ex = keyin.nextInt();

         keyin.nextLine();

         if (worker.setExtra(ex) == 0) {            // 判斷是否正常設定

               System.out.printf("程式停止運轉 \n");

               return;

         }

 

         System.out.printf("**** 列印員工薪資表 *****\n");

         System.out.printf("代號   姓名     部門    本月薪資\n");

         System.out.printf("%d\t", worker.getID());

         System.out.printf("%s\t", worker.name);

         System.out.printf("%s\t", worker.depart);

         pay = worker.getPayment();

         pay1 = (int)((double)pay/(30 * 8)) * worker.getExtra();

         System.out.printf("%d\n", pay+pay1);

    }

}

程式重點說明:

(1) Employee.class 需存在於相同目錄下

(2) 9 行:『Employee worker = new Employee();』。利用 Employee 類別產生 worker 物件,則該物件擁有原類別所宣告的方法與變數成員。

(3) 14 行:『worker.name = keyin.readLine();』。Worker.name 變數成員屬於公開性的(非隱藏性),可以直接存取。

(4) 21~24 行:『if (worker.setID(id)==0) { ..}』。呼叫 worker 物件的 setID() 方法成員,表示透過 setID() 將引數 id 值寫入 ID 變數內。執行後回傳是 0 的話,表示執行不正確。因 worker.ID 是隱藏性變數,無法直接存取,必須透過其他方法成員才行。

E直接存取隱藏性變數

無人稍修改 Ex7_1.java 程式,測試直接存取 worker.IDworker.extra worker.payment 等隱藏性變數。修改部分程式內容:Ex7_1_1.java

……..

/* 驗證直接存取 private ID 的結果 */

         id = worker.ID;            // 直接存取 private 屬性的變數成員

         System.out.printf("ID = %d\n", id);

/* 結束驗證 */                    

……..

其編譯結果如下:

D:\Java2_book\chap7\Ex7_1>javac Ex7_1_1.java

Ex7_1_1.java:27: error: ID has private access in Employee

         id = worker.ID;

                    ^

1 error

 

翻轉工作室:粘添壽

 

Java 程式設計(二) 含物件導向

 

 

翻轉電子書系列: