Java之抽象類與抽象方法
阿新 • • 發佈:2019-12-23
目錄
- Java之抽象類與抽象方法
- 抽象概念
- 抽象類與方法
- 注意事項
Java之抽象類與抽象方法
抽象概念
本篇關鍵詞是抽象,那麼何為抽象?百度百科告訴我們,抽象就是概括具體事務共同的方面、本質屬性等,而將個別的方面、屬性等捨棄的思維過程。在Java裡,也就是把各個具體的類中共有的方法提取出來,放到基類之中,而基類並不需要了解子類中該方法具體是怎麼實現的,這個基類就是所謂的抽象類,這些不需要知道具體實現方式的方法就是抽象方法。
抽象類體現模板模式的設計,抽象類作為多個子類的通用模板,子類在抽象類的基礎上進行擴充套件、改造,但子類總體上會大致保留抽象類的行為方式。
抽象類與方法
讓我們結合程式碼,好好地分析一波:
package com.my.pac18; /** * @auther Summerday */ /*抽象是很有用的重構工具,能夠讓共有的方法沿著繼承層次向上移動。*/ public abstract class Shape { //抽象類中的初始化塊 { System.out.println("Shape.instance initializer"); } //抽象類中的例項變數 private String color; //抽象類中可以有靜態方法及屬性。 public static String name="形狀"; public static void output(){ System.out.println("父類的static方法"); } //計算周長,但是並不知道具體細節的抽象方法 public abstract double calPerimeter(); //返回形狀的抽象方法 //[修飾符] abstract 返回型別 方法名(); public abstract String getType(); //抽象類中的構造器,用於被繼承 public Shape() { } public Shape(String color) { System.out.println("Shape.Shape"); this.color = color; } //抽象類中的普通例項方法 public String getColor() { return color; } } class Circle extends Shape { private double radius; public Circle(String color, double radius) { super(color); this.radius = radius; } public void setRadius(double radius) { this.radius = radius; } @Override public double calPerimeter() { return 2 * Math.PI * radius; } @Override public String getType() { return getColor() + "圓形"; } //如果從一個抽象類繼承,並建立該新類的物件,就必須給基類的所有抽象方法提供定義。 public static void main(String[] args) { Shape.output(); //Shape是抽象類,不能建立Shape類的物件 //但是可以讓Shape類的引用變數指向其子類的物件 Shape[] shapes = new Shape[]{new Circle("紅色", 5), new Rectangle("綠色", 6, 6)}; for (Shape p : shapes) { System.out.println(p.getType() + "的周長為" + p.calPerimeter()); } } } class Rectangle extends Shape { private double length; private double width; public Rectangle() { System.out.println("父類的構造器不是為了建立物件,而是供給子類繼承的"); } public Rectangle(String color, double length, double width) { super(color); this.length = length; this.width = width; } public boolean isSquare() { return length == width; } public double calPerimeter() { return (length + width) * 2; } public String getType() { if (isSquare()) return getColor() + "正方形"; return getColor() + "長方形"; } } //測試結果 父類的static方法 Shape.instance initializer Shape.Shape Shape.instance initializer Shape.Shape 紅色圓形的周長為31.41592653589793 綠色正方形的周長為24.0
順著上面的例子,我們簡單地分析一下,抽象類與抽象方法到底是啥?又需要注意些啥?
- 首先定義了一個抽象類:Shape類。可以看到,抽象類由
abstract
關鍵字修飾。
//[修飾符] abstract class 類名
public abstract class Shape
- 然後再Shape類裡定義了兩個抽象方法(方法可以被重寫,屬性不可以,抽象是針對方法而言的):
getType()
和calPerimeter()
可以看出抽象方法宣告時並沒有定義方法體,因為基類中並不需要知道具體的實現方式是怎樣,只要知道有這個方法就可以了。你建立一個圓形例項,具體如何算圓形的周長,在圓形類給出抽象方法的定義即可。
//[修飾符] abstract 返回型別 方法名();
public abstract double calPerimeter();
public abstract String getType();
注意事項
- 如果子類從抽象父類繼承而來,那麼子類就必須重寫父類的抽象方法,給出方法的具體實現形式。你的爸爸說你會算周長,你總得告訴大家周長怎麼算吧。但是,如果子類中也重寫父類的方法也宣告為抽象的話,這時父類方法在子類中的實現也無效了。就好比,你說你也不知道怎麼算周長,隔壁小王才是真的會。
@Override
public double calPerimeter() {
return 2 * Math.PI * radius;
}
@Override
public String getType() {
return getColor() + "圓形";
}
- 抽象類不能例項化,不能用new來呼叫抽象類構造器建立抽象類的例項。可以想象,既然是抽象的,建立它的例項就沒多大意義,建立具體實現的子類的例項才能解決問題。
- 抽象類可以用作一種資料型別,可以讓抽象類的引用變數指向它的子類物件,很好理解,不這樣的話,抽象帶來的好處體現在哪呢。通過抽象類的引用變數呼叫抽象類中的方法,就能夠根據動態繫結,在執行時根據引用物件的實際型別執行抽象方法的具體表現形式。
- 抽象類中是能夠有具體實現的成員方法(例項方法和類方法),以及明確的成員屬性(例項屬性和類屬性)。
//抽象類中的例項方法,子類繼承使用。
public String getColor() {
return color;
}
//抽象類中可以有靜態方法和屬性,類名.方法(屬性)呼叫。
public static String name="形狀";
public static void output(){
System.out.println("父類的static方法");
}
- 抽象類中還可以有構造器,但是僅僅是為了供給子類繼承使用,因為上面講過,抽象類無法建立例項物件!!!(重點回顧:子類無法繼承父類構造器,只是單純呼叫父類構造器的初始化程式碼,繼承和呼叫是不一樣的!!!)
//子類
public Shape() {
}
public Shape(String color) {
System.out.println("Shape.Shape");
this.color = color;
}
- 抽象類中還有程式碼塊和內部類,關於內部類之後將會學習,暫時就不舉例了。
//抽象類中的初始化塊
{
System.out.println("Shape.instance initializer");
}
一個類中如果有抽象方法,那麼這個類也一定是抽象的。畢竟你的方法定義尚且都不完全,建立你的例項又有啥用呢。但是一個抽象類中可以沒有抽象方法,只是單純不讓人建立它的例項物件。
子類是抽象,父類也可以是具體的。如上,Object類是所有類的超類,它是具體的,我們定義的Shape類是可以抽象的。
抽象是實現多型的一種機制,那麼不具備多型性的,就不能稱之為多型。諸如private、static、final修飾的方法或構造器屬於靜態繫結,不具備多型性,不能作為抽象的修飾。
本文是根據資料以及個人測試之後所得,若有錯誤或者理解不當之處,還望評論區指出,謝