抽象(abstract)和接口(interface)在Java中都是關(guān)鍵字怔软,也就說(shuō)明他們足夠重要垦细,而抽象類(lèi)和接口為我們面向?qū)ο缶幊烫峁┝朔浅4蟮膸椭O旅嫖覀兙鸵黄饋?lái)回顧這基礎(chǔ)知識(shí)挡逼。
-
抽象類(lèi)
在構(gòu)建某些未實(shí)現(xiàn)方法的類(lèi)時(shí)括改,你可能會(huì)第一個(gè)想到接口,但是抽象類(lèi)也是實(shí)現(xiàn)這個(gè)目的一種重要而必要的工具挚瘟。
創(chuàng)建抽象類(lèi)需要用到abstract關(guān)鍵字來(lái)修飾類(lèi)叹谁,我們希望通過(guò)這個(gè)通用的類(lèi)操作一系類(lèi)方法,如果沒(méi)有具體的內(nèi)容乘盖,這個(gè)抽象類(lèi)的意義只有一個(gè)焰檩,就是不讓其他類(lèi)實(shí)例化這個(gè)抽象類(lèi)的對(duì)象,只能實(shí)例化它的子類(lèi)對(duì)象订框;要達(dá)到操控析苫,Java給我們提供了抽象方法的機(jī)制,抽象方法也是使用abstract關(guān)鍵字來(lái)修飾穿扳,包含抽象方法的類(lèi)就叫做抽象類(lèi)
-
抽象類(lèi)特點(diǎn)
- 抽象類(lèi)和抽象方法必須用abstract關(guān)鍵字修飾
- 抽象類(lèi)不一定有抽象方法衩侥,有抽象方法的類(lèi)一定是抽象類(lèi)或者接口
- 抽象類(lèi)不能實(shí)例化,也就是說(shuō)不能new出來(lái)矛物,抽象類(lèi)必須由子類(lèi)實(shí)例化茫死,這其實(shí)也就是多態(tài)的一種,抽象類(lèi)多態(tài)(為什么抽象類(lèi)不能實(shí)例化履羞? 如果抽象類(lèi)實(shí)例化峦萎,實(shí)例化的抽象類(lèi)對(duì)象意思就可以調(diào)用抽象類(lèi)的抽象方法,但是抽象方法是沒(méi)有具體實(shí)現(xiàn)的忆首,也就沒(méi)有任何意義爱榔,所以抽象類(lèi)不能實(shí)例化)
- 抽象類(lèi)的子類(lèi)要么是抽象類(lèi)(實(shí)例中的Car類(lèi)),要么就重寫(xiě)抽象類(lèi)中的抽象方法(實(shí)例中的Jetta類(lèi))
- 一個(gè)類(lèi)只能繼承一個(gè)抽象類(lèi)糙及,抽象類(lèi)也可以繼承抽象類(lèi)(實(shí)例中的SuperCar 類(lèi))
-
抽象類(lèi)成員特點(diǎn):
- 成員既可以是常量也可以是變量详幽,但是abstract不能修飾成員變量,變量的值是不固定的,無(wú)法抽象
- 抽象類(lèi)也有構(gòu)造方法唇聘,他的意義在于子類(lèi)可以訪(fǎng)問(wèn)父類(lèi)的初始化數(shù)據(jù)(實(shí)例中Jetta構(gòu)造方法 super()調(diào)用了抽象父類(lèi)構(gòu)造方法)
- 成員方法既可以抽象的版姑,也可以是非抽象的,抽象方法一般是強(qiáng)制要求子類(lèi)去實(shí)現(xiàn)的方法雳灾,非抽象方法一般是重復(fù)的代碼漠酿,可以提高代碼復(fù)用性
- abstract關(guān)鍵字不能與static關(guān)鍵字(原理和抽象類(lèi)不能實(shí)例化其實(shí)是一個(gè)道理,staticx修飾的抽象方法不需要實(shí)例化可以直接調(diào)用谎亩,這顯然是沒(méi)有意義的)炒嘲、final關(guān)鍵字(final修飾的方法子類(lèi)不能重寫(xiě),abstract修飾的方法子類(lèi)強(qiáng)制重寫(xiě))匈庭、private關(guān)鍵同時(shí)出現(xiàn)(private修飾的方法子類(lèi)不能訪(fǎng)問(wèn))
-
實(shí)例
/** * @Author: mao.qitian * @Date: 2018/8/11 0011 16:25 * @Description: 汽車(chē)抽象類(lèi) */ public abstract class Car { public Car(){ System.out.println("抽象類(lèi)的構(gòu)造方法被調(diào)用"); } public void driver(){ System.out.println("所有汽車(chē)都能駕駛"); } //汽車(chē)的速度 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("開(kāi)完蘭博基尼再開(kāi)捷達(dá)速度上無(wú)法適應(yīng)"); } } /** * @Author: mao.qitian * @Date: 2018/8/11 0011 22:39 * @Description: 超跑 */ public abstract class SuperCar extends Car { //超跑的價(jià)格 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)生的是完全抽象的類(lèi),它允許創(chuàng)建者定義方法名阱持,傳參和返回類(lèi)型夭拌,但是它沒(méi)有任何方法體,只提供了形式(規(guī)則)衷咽,而未提供任何具體實(shí)現(xiàn)鸽扁。
-
接口的特點(diǎn)
- 接口使用interface關(guān)鍵字代替class修飾類(lèi),
- 類(lèi)實(shí)現(xiàn)接口用implement表示
- 和抽象類(lèi)一樣镶骗,接口也不能實(shí)例化桶现,只能由實(shí)現(xiàn)了接口的類(lèi)來(lái)進(jìn)行實(shí)例化
- 接口的子類(lèi)可以是抽象類(lèi),也可以是具體類(lèi)鼎姊,具體類(lèi)要重寫(xiě)接口的抽象方法
-
接口成員特點(diǎn)
- 接口中定義的變量都是常量骡和,默認(rèn)修飾符為 public static final
-
- 接口沒(méi)有構(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類(lèi)的構(gòu)造方法,方法默認(rèn)繼承Objetc類(lèi) } @Override public void b() { } }
- 接口中的成員方法只能是抽象方法相寇,默認(rèn)修飾符為 public abstract
- 接口中的所以成員方法和變量都是公共的(public)
-
接口的應(yīng)用
策略模式:定義一系列算法慰于,把每一個(gè)算法封裝起來(lái),并且使他們可以相互替換唤衫。策略模式使得算法可獨(dú)立于使用它的客戶(hù)端而獨(dú)立變化婆赠。
-
三個(gè)角色
- 上下文角色(Context):操作我們制定策略的上下文環(huán)境,使用策略的通用調(diào)用
- 抽象策略角色(Stragety):策略佳励,算法的抽象休里,通常是一個(gè)接口
- 策略的實(shí)現(xiàn)角色(ConcreteStragety):實(shí)現(xiàn)抽象的策略接口,具體實(shí)現(xiàn)這個(gè)策略
- 實(shí)例
實(shí)現(xiàn)學(xué)校教師的獎(jiǎng)金發(fā)放植兰,教師有屬性:編號(hào)份帐、姓名璃吧,教學(xué)總工作量楣导,獎(jiǎng)金 獎(jiǎng)金的計(jì)算方法為: x*30 (當(dāng)職稱(chēng)為教授時(shí)) y= x*25 (當(dāng)職稱(chēng)為副教授時(shí)) x*20 (當(dāng)職稱(chēng)為講師時(shí)) public interface Function { //接口定義抽象方法 (Stragety) public double Money(double x); } public class A implements Function { //教授獎(jiǎng)金計(jì)算 public double Money(double x) { return x*30; } public class B implements Function { //副教授獎(jiǎng)金計(jì)算 public double Money(double x) { return x*25; } } public class C implements Function { //講師獎(jiǎng)金計(jì)算 public double Money(double x) { return x*20; } } public class myMoney { //上下文角色 Function s; double M;//工時(shí) String name;//教師姓名 String type;//教師職稱(chēng) int number;//教師編號(hào) public void S(double X,String N,int Num,String Type){ this.M=X; this.name=N; this.number=Num; this.type=Type; } //獎(jiǎng)金計(jì)算方式 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("請(qǐng)輸入職位:"); String Type=sc.next(); System.out.println("請(qǐng)輸入姓名:"); String N=sc.next(); System.out.println("請(qǐng)輸入編號(hào):"); int Num=sc.nextInt(); System.out.println("請(qǐng)輸入工時(shí):"); double X=sc.nextDouble(); f.S(X, N, Num, Type); System.out.println(N+獎(jiǎng)金為"+f.getMoney());
-
類(lèi)與類(lèi),類(lèi)與接口畜挨,接口與接口之間的關(guān)系
- 類(lèi)與類(lèi)之間筒繁,一個(gè)類(lèi)只能繼承一個(gè)類(lèi)噩凹,但是類(lèi)可以多層繼承
- 類(lèi)與接口則是實(shí)現(xiàn)關(guān)系,一個(gè)類(lèi)可以繼承一個(gè)接口毡咏,也可以繼承多個(gè)接口驮宴,也可以繼承一個(gè)類(lèi)的同時(shí)實(shí)現(xiàn)多個(gè)接口
- 接口與接口之間是繼承關(guān)系,一個(gè)接口可以繼承另一個(gè)接口呕缭,也可以繼承多個(gè)接口
/**
* @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() { }
}
-
抽象類(lèi)和接口的區(qū)別
類(lèi) | 成員區(qū)別 | 繼承關(guān)系區(qū)別 | 設(shè)計(jì)理念區(qū)別 |
---|---|---|---|
抽象類(lèi) | 成員變量可以是常量,也可以是變量恢总,有構(gòu)造方法迎罗,成員方法可以是抽象的也可以是非抽象的 | 單繼承,多層繼承 | 被繼承的體現(xiàn)是“is a”的關(guān)系片仿,抽象類(lèi)中定義的是該繼承體系的共性功能 |
接口 | 成員變量只能是常量纹安,沒(méi)有構(gòu)造方法,成員方法只能是抽象的 | 實(shí)現(xiàn)砂豌,可以實(shí)現(xiàn)多個(gè)接口 | 被繼承的體現(xiàn)是“l(fā)ike a”的關(guān)系厢岂,接口中定義的是該繼承體現(xiàn)的擴(kuò)展功能 |
最后
還是那句話(huà),好記性不如爛筆頭阳距,通過(guò)這一篇文章塔粒,再次鞏固了基礎(chǔ)知識(shí)。如果文章中有寫(xiě)得不對(duì)的地方娄涩,請(qǐng)給我留言指出窗怒,大家一起學(xué)習(xí)進(jìn)步。
-
參考資料:
- 《Android進(jìn)階之光》
- 《Java編程思想》(第四版)