抽象(abstract)和介面(interface)在Java中都是關鍵字,也就說明他們足夠重要,而抽象類和介面為我們物件導向程式設計提供了非常大的幫助。下面我們就一起來回顧這基礎知識。
-
抽象類
-
在構建某些未實現方法的類時,你可能會第一個想到介面,但是抽象類也是實現這個目的一種重要而必要的工具。
-
建立抽象類需要用到abstract關鍵字來修飾類,我們希望通過這個通用的類操作一系類方法,如果沒有具體的內容,這個抽象類的意義只有一個,就是不讓其他類例項化這個抽象類的物件,只能例項化它的子類物件;要達到操控,Java給我們提供了抽象方法的機制,抽象方法也是使用abstract關鍵字來修飾,包含抽象方法的類就叫做抽象類
-
抽象類特點
-
- 抽象類和抽象方法必須用abstract關鍵字修飾
-
- 抽象類不一定有抽象方法,有抽象方法的類一定是抽象類或者介面
-
- 抽象類不能例項化,也就是說不能new出來,抽象類必須由子類例項化,這其實也就是多型的一種,抽象類多型(為什麼抽象類不能例項化? 如果抽象類例項化,例項化的抽象類物件意思就可以呼叫抽象類的抽象方法,但是抽象方法是沒有具體實現的,也就沒有任何意義,所以抽象類不能例項化)
-
- 抽象類的子類要麼是抽象類(例項中的Car類),要麼就重寫抽象類中的抽象方法(例項中的Jetta類)
-
- 一個類只能繼承一個抽象類,抽象類也可以繼承抽象類(例項中的SuperCar 類)
-
-
抽象類成員特點:
-
- 成員既可以是常量也可以是變數,但是abstract不能修飾成員變數,變數的值是不固定的,無法抽象
-
- 抽象類也有構造方法,他的意義在於子類可以訪問父類的初始化資料(例項中Jetta構造方法 super()呼叫了抽象父類構造方法)
-
- 成員方法既可以抽象的,也可以是非抽象的,抽象方法一般是強制要求子類去實現的方法,非抽象方法一般是重複的程式碼,可以提高程式碼複用性
-
- abstract關鍵字不能與static關鍵字(原理和抽象類不能例項化其實是一個道理,staticx修飾的抽象方法不需要例項化可以直接呼叫,這顯然是沒有意義的)、final關鍵字(final修飾的方法子類不能重寫,abstract修飾的方法子類強制重寫)、private關鍵同時出現(private修飾的方法子類不能訪問)
-
-
例項
/** * @Author: mao.qitian * @Date: 2018/8/11 0011 16:25 * @Description: 汽車抽象類 */ public abstract class Car { public Car(){ System.out.println("抽象類的構造方法被呼叫"); } public void driver(){ System.out.println("所有汽車都能駕駛"); } //汽車的速度 public abstract void speed(); } /** * @Author: mao.qitian@gxxmt.com * @Date: 2018/8/11 0011 16:29 * @Description: 捷達 */ public class Jetta extends Car{ public Jetta(){ super(); } @Override public void speed() { System.out.println("開完蘭博基尼再開捷達速度上無法適應"); } } /** * @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)
-
介面使抽象的更向前邁進了一步,interface關鍵字修飾方法產生的是完全抽象的類,它允許建立者定義方法名,傳參和返回型別,但是它沒有任何方法體,只提供了形式(規則),而未提供任何具體實現。
-
介面的特點
-
- 介面使用interface關鍵字代替class修飾類,
-
- 類實現介面用implement表示
-
- 和抽象類一樣,介面也不能例項化,只能由實現了介面的類來進行例項化
-
- 介面的子類可以是抽象類,也可以是具體類,具體類要重寫介面的抽象方法
-
-
介面成員特點
-
- 介面中定義的變數都是常量,預設修飾符為 public static final
-
- 介面沒有構造方法
/** * @Author: mao.qitian * @Date: 2018/8/12 0012 0:22 * @Description: */ public interface A { public void b(); } class C implements A{ public C(){ super();//呼叫的是Objetc類的構造方法,方法預設繼承Objetc類 } @Override public void b() { } } 複製程式碼
-
- 介面中的成員方法只能是抽象方法,預設修飾符為 public abstract
-
- 介面中的所以成員方法和變數都是公共的(public)
-
-
介面的應用
-
策略模式:定義一系列演算法,把每一個演算法封裝起來,並且使他們可以相互替換。策略模式使得演算法可獨立於使用它的客戶端而獨立變化。
-
三個角色
- 上下文角色(Context):操作我們制定策略的上下文環境,使用策略的通用呼叫
- 抽象策略角色(Stragety):策略,演算法的抽象,通常是一個介面
- 策略的實現角色(ConcreteStragety):實現抽象的策略介面,具體實現這個策略
- 例項
實現學校教師的獎金髮放,教師有屬性:編號、姓名,教學總工作量,獎金 獎金的計算方法為: x*30 (當職稱為教授時) y= x*25 (當職稱為副教授時) x*20 (當職稱為講師時) 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()); 複製程式碼
-
-
-
類與類,類與介面,介面與介面之間的關係
- 類與類之間,一個類只能繼承一個類,但是類可以多層繼承
- 類與介面則是實現關係,一個類可以繼承一個介面,也可以繼承多個介面,也可以繼承一個類的同時實現多個介面
- 介面與介面之間是繼承關係,一個介面可以繼承另一個介面,也可以繼承多個介面
/** * @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() { } } 複製程式碼
-
抽象類和介面的區別
類 | 成員區別 | 繼承關係區別 | 設計理念區別 |
---|---|---|---|
抽象類 | 成員變數可以是常量,也可以是變數,有構造方法,成員方法可以是抽象的也可以是非抽象的 | 單繼承,多層繼承 | 被繼承的體現是“is a”的關係,抽象類中定義的是該繼承體系的共性功能 |
介面 | 成員變數只能是常量,沒有構造方法,成員方法只能是抽象的 | 實現,可以實現多個介面 | 被繼承的體現是“like a”的關係,介面中定義的是該繼承體現的擴充套件功能 |
最後
還是那句話,好記性不如爛筆頭,通過這一篇文章,再次鞏固了基礎知識。如果文章中有寫得不對的地方,請給我留言指出,大家一起學習進步。
-
參考資料:
- 《Android進階之光》
- 《Java程式設計思想》(第四版)
- 同步簡書地址