【Java入門提高篇】Day3 抽象類別與介面的比較

來源:互聯網
上載者:User

標籤:作業系統   class   travel   關注   ext   car   oid   color   適合   

  抽象類別跟介面都講完了,現在來做一個比較。

  其實說實話,沒有多大的可比較性,它們是完全不同的兩個東西,它們的抽象不在同一個層級上。但是為了讓大家更好的理解,還是做一個比較吧,畢竟它們都很抽象(233)。

  首先是文法層面上的對比

  1)抽象類別跟介面都不能被執行個體化,因為它們都很虛嘛。但是在存取權限上,兩者有一定的區別。

  a、抽象類別中的抽象方法(其前有abstract修飾)不能用private、static、synchronized、native存取修飾詞修飾。理由很簡單,容我慢慢道來。

  抽象方法是沒有方法體的,它的目的就是用來繼承的,所以如果使用private修飾,不就不能被繼承了嗎?這就違背了它的設計初衷了,所以不能用private來修飾抽象方法。至於static,用它來修飾的方法可以不執行個體化就可以直接調用,但是抽象方法沒有方法體,使用static修飾就沒有意義了。synchronized是用來加鎖的,如果修飾類中的方法的話,就相當於用this變數鎖,但是抽象類別是不能被執行個體化的,抽象方法也不是在本類中實現而是在子類中實現的,所以鎖應該是子類所屬,所以抽象方法不能用synchronized關鍵字修飾;至於native,這個跟abstract關鍵字本身就是衝突的,abstract聲明方法交給子類實現,而native則是交給本地作業系統實現,如果同時出現,那就相當於把實現交給子類,又交給本地作業系統,那最後到底由誰來實現呢?

  綜上所述,抽象類別中的抽象方法只能用public和protected修飾。

  b.介面中的方法全部為public abstract修飾,不能使用其他修飾符,而且預設情況(不加任何修飾符)下,也是public abstract的,因為介面只能被類實現,不能被類繼承,所以不能使用protected修飾,但介面是可以繼承介面的。

 

  2)抽象類別跟普通類的唯一區別就是不能被執行個體化,可以有抽象方法,所以它可以有建構函式,靜態方法,靜態代碼塊,可以有普通的成員變數和方法。但是介面就不一樣了,介面只能聲明public abstract的方法和public static final的成員變數。

  3)抽象類別本質上還是一個類,只能單繼承,一個類只能繼承一個抽象類別,但可以實現多個介面。

 

  其次是概念上的比較

  1)抽象類別跟介面的抽象角度不一樣,抽象類別一般是對某些具有相似屬性和方法的類進行抽象,抽象出一個統一的父類。而介面則更多的是多一組特定行為的抽象,關注的是行為,而具有這些行為的類之間可能並沒有太大的關聯性。

  比如說,飛機能上天,鳥能上天,你要是厲害一點,應該也能上天(逃),但顯然兩者之間的關聯度不大,如果硬是要給它們插上一個公用的父類的話,似乎不合情理,看起來就像這樣:

  

public abstract class Flyer {    public abstract void fly();}

  然後定義兩個類來繼承它:

public class Airplane extends Flyer {    @Override    public void fly() {        System.out.println("Airplane is flying.");    }}
public class Bird extends Flyer {    @Override    public void fly() {        System.out.println("Bird is flying.");    }}

  好的,現在寫一個測試類別:

public class Test {    public static void main(String[] args) {        Flyer[] flyer = new Flyer[2];        flyer[0] = new Airplane();        flyer[1] = new Bird();        for (Flyer f:flyer){            f.fly();        }    }}

  運行結果如下:

Airplane is flying.Bird is flying.

  乍眼一看,好像運行良好,但是仔細想想,將兩個關聯度很低的類強行插上一個父類,似乎有些不妥,畢竟飛機跟鳥除了都能飛以外,基本沒有什麼相似的地方了,而且兩者的飛行方式,飛行速度和高度都相去甚遠,也就是說除了這個fly的方法,其他方法都要在各自的子類實現,而且一個類只能繼承一個抽象類別,所以Bird類和Airplane類就無法再繼承其他類了,這樣就反而限制了程式的靈活性。所以,這種時候,還是比較適合使用介面:

public interface IFlyable {    //聲明Fly方法    void fly();}

  而此時只需要將Airplane類和Bird類的extends Flyer改成implement Flyable即可。

public class Airplane implements IFlyable {    //實現Fly方法    @Override    public void fly() {        System.out.println("Airplane is flying.");    }}
public class Bird implements IFlyable {    //實現Fly方法    @Override    public void fly() {        System.out.println("Bird is flying.");    }}

  再修改一下Test類:

public class Test {    public static void main(String[] args) {        IFlyable[] flyer = new IFlyable[2];        flyer[0] = new Airplane();        flyer[1] = new Bird();        for (IFlyable f:flyer){            f.fly();        }    }}

  輸出如下:

Airplane is flying.Bird is flying.

  也許從這個栗子還沒法明顯的看出兩者的區別,那麼我們再換一個栗子,人可以坐飛機,可以坐火車,還可以坐汽車,只要它們有載人功能即可,那用介面實現如下:

public interface ICarryPassenger {    //聲明載客方法    void carry(Passenger passenger);}

  定義一個乘客類,用姓名來區分各個乘客。

public class Passenger {    private String name;//乘客姓名    public Passenger(String name){        this.name = name;    }    public String getName() {        return name;    }    //出行方式    public void travelBy(ICarryPassenger ic){        ic.carry(this);    }}

  分別定義汽車類,火車類,飛機類,它們都實現ICarryPassenger介面,飛機還可以實現IFlyable介面(雖然沒有用到。。):

public class Car implements ICarryPassenger {    int passengerNum;    //實現carry方法    @Override    public void carry(Passenger passenger) {        System.out.println("Passenger:"+passenger.getName()+" travel by Car.");        passengerNum++;        System.out.println("Car carries: "+passengerNum+" passenger.");    }}
public class Train implements ICarryPassenger {    int passengerNum;    @Override    public void carry(Passenger passenger) {        System.out.println("Passenger:"+passenger.getName()+" travel by Train.");        passengerNum++;        System.out.println("Train carries: "+passengerNum+" passenger.");    }}
public class Airplane implements IFlyable,ICarryPassenger{    private int passengerNum;//乘客數量    //實現Fly方法    @Override    public void fly() {        System.out.println("Airplane is flying.");    }    //實現carry方法    @Override    public void carry(Passenger passenger) {        System.out.println("Passenger:"+passenger.getName()+" travel by Airplane.");        passengerNum++;        System.out.println("Airplane carries: "+passengerNum+" passengers.");    }}

  好的,現在我們寫一個測試類別來進行測試:

public class Test {    public static void main(String[] args) {        //有6個乘客想要去旅遊,對於旅行方式沒有側重,隨機分配交通工具        Random random = new Random();        Passenger[] passengers = new Passenger[6];//聲明6個乘客        for (int i=0;i<6;i++){            passengers[i] = new Passenger("Passenger["+i+"]");        }        ICarryPassenger[] icp = new ICarryPassenger[3];//聲明3種交通方式        icp[0] = new Airplane();        icp[1] = new Car();        icp[2] = new Train();        for (int i=0;i<6;i++){            passengers[i].travelBy(icp[random.nextInt(3)]);        }    }}

  輸出如下:

Passenger:Passenger[0] travel by Airplane.Airplane carries: 1 passengers.Passenger:Passenger[1] travel by Train.Train carries: 1 passenger.Passenger:Passenger[2] travel by Airplane.Airplane carries: 2 passengers.Passenger:Passenger[3] travel by Car.Car carries: 1 passenger.Passenger:Passenger[4] travel by Train.Train carries: 2 passenger.Passenger:Passenger[5] travel by Airplane.Airplane carries: 3 passengers.

  因為飛機跟火車,汽車之間並沒有太大關聯,顯然無法直接抽象出父類,它們僅有相同的行為,那就是載客,所以使用介面是最合適的。

  至此,本篇講解完畢,想必通過這一篇的講解,對於抽象類別和介面的區別應該有了更好的理解吧,如果有更好的栗子,歡迎大家留言交流,也歡迎大家繼續關注。

 

【Java入門提高篇】Day3 抽象類別與介面的比較

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.