抽象(abstract)和接口(interface)在Java中都是關(guān)鍵字,也就說明他們足夠重要,而抽象類和接口為我們面向?qū)ο缶幊烫峁┝朔浅4蟮膸椭?。下面我們就一起來回顧這基礎(chǔ)知識。
-
抽象類
在構(gòu)建某些未實現(xiàn)方法的類時,你可能會第一個想到接口,但是抽象類也是實現(xiàn)這個目的一種重要而必要的工具。
創(chuàng)建抽象類需要用到abstract關(guān)鍵字來修飾類,我們希望通過這個通用的類操作一系類方法,如果沒有具體的內(nèi)容,這個抽象類的意義只有一個,就是不讓其他類實例化這個抽象類的對象,只能實例化它的子類對象;要達(dá)到操控,Java給我們提供了抽象方法的機制,抽象方法也是使用abstract關(guān)鍵字來修飾,包含抽象方法的類就叫做抽象類
-
抽象類特點
- 抽象類和抽象方法必須用abstract關(guān)鍵字修飾
- 抽象類不一定有抽象方法,有抽象方法的類一定是抽象類或者接口
- 抽象類不能實例化,也就是說不能new出來,抽象類必須由子類實例化,這其實也就是多態(tài)的一種,抽象類多態(tài)(為什么抽象類不能實例化? 如果抽象類實例化,實例化的抽象類對象意思就可以調(diào)用抽象類的抽象方法,但是抽象方法是沒有具體實現(xiàn)的,也就沒有任何意義,所以抽象類不能實例化)
- 抽象類的子類要么是抽象類(實例中的Car類),要么就重寫抽象類中的抽象方法(實例中的Jetta類)
- 一個類只能繼承一個抽象類,抽象類也可以繼承抽象類(實例中的SuperCar 類)
-
抽象類成員特點:
- 成員既可以是常量也可以是變量,但是abstract不能修飾成員變量,變量的值是不固定的,無法抽象
- 抽象類也有構(gòu)造方法,他的意義在于子類可以訪問父類的初始化數(shù)據(jù)(實例中Jetta構(gòu)造方法 super()調(diào)用了抽象父類構(gòu)造方法)
- 成員方法既可以抽象的,也可以是非抽象的,抽象方法一般是強制要求子類去實現(xiàn)的方法,非抽象方法一般是重復(fù)的代碼,可以提高代碼復(fù)用性
- abstract關(guān)鍵字不能與static關(guān)鍵字(原理和抽象類不能實例化其實是一個道理,staticx修飾的抽象方法不需要實例化可以直接調(diào)用,這顯然是沒有意義的)、final關(guān)鍵字(final修飾的方法子類不能重寫,abstract修飾的方法子類強制重寫)、private關(guān)鍵同時出現(xiàn)(private修飾的方法子類不能訪問)
-
實例
/** * @Author: mao.qitian * @Date: 2018/8/11 0011 16:25 * @Description: 汽車抽象類 */ public abstract class Car { public Car(){ System.out.println("抽象類的構(gòu)造方法被調(diào)用"); } public void driver(){ System.out.println("所有汽車都能駕駛"); } //汽車的速度 public abstract void speed(); } /** * @Author: mao.qitian@gxxmt.com * @Date: 2018/8/11 0011 16:29 * @Description: 捷達(dá) */ public class Jetta extends Car{ public Jetta(){ super(); } @Override public void speed() { System.out.println("開完蘭博基尼再開捷達(dá)速度上無法適應(yīng)"); } } /** * @Author: mao.qitian * @Date: 2018/8/11 0011 22:39 * @Description: 超跑 */ public abstract class SuperCar extends Car { //超跑的價格 public abstract void expensive (); } /** * @Author: mao.qitian * @Date: 2018/8/11 0011 16:27 * @Description: 蘭博基尼 */ public class Lamborghini extends SuperCar { @Override public void speed() { System.out.println("蘭博基尼速度兩秒破百"); } @Override public void expensive() { } }
-
接口(interface)
接口使抽象的更向前邁進(jìn)了一步,interface關(guān)鍵字修飾方法產(chǎn)生的是完全抽象的類,它允許創(chuàng)建者定義方法名,傳參和返回類型,但是它沒有任何方法體,只提供了形式(規(guī)則),而未提供任何具體實現(xiàn)。
-
接口的特點
- 接口使用interface關(guān)鍵字代替class修飾類,
- 類實現(xiàn)接口用implement表示
- 和抽象類一樣,接口也不能實例化,只能由實現(xiàn)了接口的類來進(jìn)行實例化
- 接口的子類可以是抽象類,也可以是具體類,具體類要重寫接口的抽象方法
-
接口成員特點
- 接口中定義的變量都是常量,默認(rèn)修飾符為 public static final
-
- 接口沒有構(gòu)造方法
/** * @Author: mao.qitian * @Date: 2018/8/12 0012 0:22 * @Description: */ public interface A { public void b(); } class C implements A{ public C(){ super();//調(diào)用的是Objetc類的構(gòu)造方法,方法默認(rèn)繼承Objetc類 } @Override public void b() { } } - 接口中的成員方法只能是抽象方法,默認(rèn)修飾符為 public abstract
- 接口中的所以成員方法和變量都是公共的(public)
-
接口的應(yīng)用
策略模式:定義一系列算法,把每一個算法封裝起來,并且使他們可以相互替換。策略模式使得算法可獨立于使用它的客戶端而獨立變化。
-
三個角色
- 上下文角色(Context):操作我們制定策略的上下文環(huán)境,使用策略的通用調(diào)用
- 抽象策略角色(Stragety):策略,算法的抽象,通常是一個接口
- 策略的實現(xiàn)角色(ConcreteStragety):實現(xiàn)抽象的策略接口,具體實現(xiàn)這個策略
- 實例
實現(xiàn)學(xué)校教師的獎金發(fā)放,教師有屬性:編號、姓名,教學(xué)總工作量,獎金 獎金的計算方法為: x*30 (當(dāng)職稱為教授時) y= x*25 (當(dāng)職稱為副教授時) x*20 (當(dāng)職稱為講師時) public interface Function { //接口定義抽象方法 (Stragety) public double Money(double x); } public class A implements Function { //教授獎金計算 public double Money(double x) { return x*30; } public class B implements Function { //副教授獎金計算 public double Money(double x) { return x*25; } } public class C implements Function { //講師獎金計算 public double Money(double x) { return x*20; } } public class myMoney { //上下文角色 Function s; double M;//工時 String name;//教師姓名 String type;//教師職稱 int number;//教師編號 public void S(double X,String N,int Num,String Type){ this.M=X; this.name=N; this.number=Num; this.type=Type; } //獎金計算方式 public double getMoney(){ if(type.equals("教授")) s=new A(); if(type.equals("副教授")) s=new B(); if(type.equals("講師")) s=new C(); return s.Money(M); } } //使用 myMoney f=new myMoney(); Scanner sc=new Scanner(System.in); System.out.println("請輸入職位:"); String Type=sc.next(); System.out.println("請輸入姓名:"); String N=sc.next(); System.out.println("請輸入編號:"); int Num=sc.nextInt(); System.out.println("請輸入工時:"); double X=sc.nextDouble(); f.S(X, N, Num, Type); System.out.println(N+獎金為"+f.getMoney());
-
類與類,類與接口,接口與接口之間的關(guān)系
- 類與類之間,一個類只能繼承一個類,但是類可以多層繼承
- 類與接口則是實現(xiàn)關(guān)系,一個類可以繼承一個接口,也可以繼承多個接口,也可以繼承一個類的同時實現(xiàn)多個接口
- 接口與接口之間是繼承關(guān)系,一個接口可以繼承另一個接口,也可以繼承多個接口
/**
* @Author: mao.qitian
* @Date: 2018/8/12 0012 0:22
* @Description:
*/
public interface A {
public void a();
}
interface B {
public void b();
}
interface C extends B,A{ //接口與接口之間繼承,多繼承
public void c();
}
class D implements A,B,C{
@Override
public void a() { }
@Override
public void b() { }
@Override
public void c() { }
}
-
抽象類和接口的區(qū)別
| 類 | 成員區(qū)別 | 繼承關(guān)系區(qū)別 | 設(shè)計理念區(qū)別 |
|---|---|---|---|
| 抽象類 | 成員變量可以是常量,也可以是變量,有構(gòu)造方法,成員方法可以是抽象的也可以是非抽象的 | 單繼承,多層繼承 | 被繼承的體現(xiàn)是“is a”的關(guān)系,抽象類中定義的是該繼承體系的共性功能 |
| 接口 | 成員變量只能是常量,沒有構(gòu)造方法,成員方法只能是抽象的 | 實現(xiàn),可以實現(xiàn)多個接口 | 被繼承的體現(xiàn)是“l(fā)ike a”的關(guān)系,接口中定義的是該繼承體現(xiàn)的擴展功能 |
最后
還是那句話,好記性不如爛筆頭,通過這一篇文章,再次鞏固了基礎(chǔ)知識。如果文章中有寫得不對的地方,請給我留言指出,大家一起學(xué)習(xí)進(jìn)步。
-
參考資料:
- 《Android進(jìn)階之光》
- 《Java編程思想》(第四版)