Java 從入門到進階之路(十三)


在之前的文章我們介紹了一下 Java 類的 private,static,final,本章我們來看一下 Java 中的抽象類和抽象方法。

我們先來看下面一段代碼:

 1 // 根據周長求面積
 2 class Square { // 方形類
 3     double c;
 4 
 5     double area() { // 方形面積
 6         return 0.0625 * c * c;
 7     }
 8 }
 9 
10 class Circle { // 圓形類
11     double c;
12 
13     double area() { // 圓形面積
14         return 0.0796 * c * c;
15     }
16 }

在上面的代碼中我們分別定義了一個方形類和圓形類,然后根據周長計算出各自的面積。咋上面的代碼中可以看出這兩段代碼都有相同的地方,我們第一感覺就是將相同的部分單獨封裝成一個父類,然后通過集成的方式完成,如下:

 1 class Shape { // 圖形
 2     double c;
 3 
 4     double area() { // 如果不 return 的話會編譯錯誤
 5         return 系數 * c * c; // 不同形狀系數不同
 6     }
 7 
 8     void area() { // 不會出現編譯錯誤,但是這樣寫這個方法沒有任何意義
 9 
10     }
11 }
12 
13 // 根據周長求面積
14 class Square extends Shape { // 方形類
15 
16 }
17 
18 class Circle extends Shape { // 圓形類
19 
20 }

在上面的代碼中我們單獨封裝了一個 Shape 類,但是有一個問題,周長 c 是公共的沒問題,但是面積 area() 方法卻由於不同圖形的面積系數不同,沒法解決,此時就需要利用抽象方法來解決了,即在方法體前面加 abstract 關鍵字,如下:

1 class Shape { // 圖形
2     double c;
3 
4     abstract double area(); // 抽象方法 --不完整
5 
6 }

抽象方法的定義:

 1、由 abstract 修飾;

 2、只有方法的定義,沒有方法的實現(大括號都沒有);

但是抽象方法是不完整的,所以我們需要將類也變成抽象類,如下:

1 abstract class Shape { // 圖形 --不完整
2     double c;
3 
4     abstract double area(); // 抽象方法 --不完整
5 
6 }

抽象類的定義:

 1、由 abstract 修飾;

 2、包含抽象方法的類必須是抽象類;

 3、抽象類不能被實例化;

 4、抽象類是需要被繼承的,所以子類需要:

  1)重寫所有抽象方法 --- 常用

  2)也聲明未抽象類 ---不常用

 

在第 4 點鍾抽象類是需要被繼承的,如下代碼:

 1 abstract class Shape { // 圖形 --不完整
 2     double c;
 3 
 4     abstract double area(); // 抽象方法 --不完整
 5 
 6 }
 7 
 8 
 9 class Square extends Shape { // 編譯錯誤,因為繼承了 Shape 類,Shape 類中包含 抽象方法
10 
11 }
12 
13 // 改進
14 abstract class Square extends Shape { // 不報錯誤,但是 Square 類也變成了抽象類
15 
16 }
17 
18 // 改進
19 class Square extends Shape { // 不報錯誤,將 Square 類中的抽象類重寫為非抽象類
20     double area() {
21         return 0.0625 * c * c;
22     }
23 }

在上面的代碼中我們實現了抽象類和抽象方法,但是貌似看上去多此一舉,如下:

1 class Shape { // 圖形 只提取公共變量 c
2     double c;
3 }
4 
5 abstract class Shape { // 圖形 --不完整
6     double c;
7 
8     abstract double area(); // 抽象方法 --不完整
9 }

在上面的代碼中,我們完全可以只提取公共變量 周長c 就可以了,因為 area() 方法反正是要重寫的,何必多此一舉呢。

接下來我們看下面的需求,就是分別以 周長 c = 1,2,3 來創建三個 Square 和 Circle 類,然后找出這 6 個圖形中面積最大的一個。我們首先想到的方法應該是這樣:

 1 public class HelloWorld {
 2     public static void main(String[] args) {
 3         Square[] squares = new Square[3];
 4         squares[0] = new Square(1);
 5         squares[1] = new Square(2);
 6         squares[2] = new Square(3);
 7 
 8         Circle[] circles = new Circle[3];
 9         circles[0] = new Circle(1);
10         circles[1] = new Circle(2);
11         circles[2] = new Circle(3);
12 
13         /**
14          * 1、找到 squares 中最大面積 sMax
15          * 2、找到 circles 中最大面積 cMax
16          * 3、比較 sMax 與 cMax 的最大值
17          */
18 
19     }
20 }
21 
22 class Shape {
23     double c;
24 }
25 
26 class Square extends Shape {
27     Square(double c) {
28         this.c = c;
29     }
30 
31     double area() {
32         return 0.0625 * c * c;
33     }
34 }
35 
36 
37 class Circle extends Shape {
38     Circle(double c) {
39         this.c = c;
40     }
41 
42     double area() {
43         return 0.0796 * c * c;
44     }
45 }

在上面的代碼中,我們先定義一個數組,里面存數三個周長 c = 1,2,3 的 Square,再定義一個數組,里面存放三個周長 c = 1,2,3 的 Circle,然后我們分別計算出兩個數組中面積的最大值再比較出面積最大的一個,這個可以解決我們的問題,但是如果再價格六邊形,就需要再定義一個數組,那么我們上面寫的代碼就出現了 代碼重復,擴展性差,維護性差 的問題。

接下來我們用抽象類的方法來寫一下:

 1 public class HelloWorld {
 2     public static void main(String[] args) {
 3         Shape[] shapes = new Shape[6]; // 向上造型
 4         shapes[0] = new Square(1);
 5         shapes[1] = new Square(2);
 6         shapes[2] = new Square(3);
 7         shapes[3] = new Circle(1);
 8         shapes[4] = new Circle(2);
 9         shapes[5] = new Circle(3);
10 
11         double max = shapes[0].area(); // 先假設第一個為最大值
12         for(int i=1;i<shapes.length;i++){
13             double area = shapes[i].area();
14             if(area > max){
15                 max = area;
16             }
17         }
18         System.out.println(max);
19     }
20 }
21 
22 abstract class Shape {
23     double c;
24     abstract double area();
25 }
26 
27 class Square extends Shape {
28     Square(double c) {
29         this.c = c;
30     }
31 
32     double area() {
33         return 0.0625 * c * c;
34     }
35 }
36 
37 
38 class Circle extends Shape {
39     Circle(double c) {
40         this.c = c;
41     }
42 
43     double area() {
44         return 0.0796 * c * c;
45     }
46 }

在上面的代碼中我們先定義了一個 Shape[] 數組,然后通過向上造型的方式向數組中分別添加 Square 和 Circle,這樣就只在一個數組中比較最大值就可以了,當再添加五邊形,六邊形時只需要擴充 Shape[] 數組就可以了。

 抽象類的意義:

 1、為其子類提供一個公共的類型 -- 向上造型;

 2、封裝子類中的重復內容(成員變量和方法);

 3、定義有抽象方法,子類雖然有不同的實現,但該方法的定義是一致的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM