面向對象設計過程當中重要的一點是如何進行抽象,即把「問題空間」中的元素與「方案空間」中的元素創建理想的一對一的映射關係。抽象類和接口即是抽象過程當中的產物。java
1、抽象類編程
咱們知道,對象是經過類來產生的,可是並不是全部的類均可以描述具體的對象。設計模式
若是一個類中不包含足夠的信息來描述具體的對象,就成爲了抽象類。抽象類是對一類有着相同特徵,但細節上卻有着不一樣表現的對象的抽象。好比,鳥類都會叫,可是不一樣的鳥叫法確定是不一樣的,能夠抽象出「叫」這個概念。微信
定義下面一個鳥類:this
public abstract class Bird {spa
private String color;設計
public String getColor() {對象
return color;繼承
}接口
public void setColor(String color) {
this.color = color;
}
public Bird(){
}
public abstract void sing();//鳴叫
}
//喜鵲
class Magpie extends Bird{
public void sing() {
System.out.println("I can sing in a whisper. ");
}
}
抽象類特徵:
(1)抽象類用abstract關鍵字修飾
(2)抽象類中的抽象方法用abstract關鍵字修飾,沒有方法體(具體實現)。
(3)抽象類能夠包含非抽象方法
(4)抽象類能夠不包含抽象方法(設計成抽象類就沒什麼意義了吧。。。),但包含抽象方法的類必定是抽象類
(5)抽象類本質也是類,只能單繼承
(6)抽象類不能實例化,不能new。咱們前面說過它不描述具體的對象,確定也不能實例化了
(7)抽象類能夠有實例變量和構造方法
2、接口
接口是一組方法特徵的集合,是契約,規定了你能夠作什麼。軟件設計過程當中要依賴抽象,而非具體實現。
像咱們電腦上的usb接口,不管你是硬盤、u盤、仍是手機,只要你實現了usb規定的接口,便可以聯通電腦。
上面抽象類的例子中,我想加入一個「飛」的功能,考慮到並不是全部的鳥都會飛,好比:企鵝,鴕鳥,鴨子等等,該怎麼辦呢?
修改抽象類確定是不合適的:一、違反開閉原則,2:會使得全部的子類都繼承到「飛」這一功能,咱們會看到滿天的鴨子在飛了^_^。
咱們能夠定義下面一個接口:
public interface IFly {
void fly();
}
//喜鵲能夠實現IBird中的接口:
class Magpie extends Bird implements IFly {
public void sing() {
System.out.println("I can sing in a whisper. ");
}
public void fly(){
System.out.println("我會飛了!");
}
}
喜鵲實現了IFly中的fly接口,終於能夠飛起來了。
那若是須要給鳥類增長一個游泳的功能呢?本身去想。。。
接口的特徵:
(1)修飾符:public,abstract,default(不寫)
(2)關鍵字:interface
(3)接口中的方法都是抽象方法,不能夠有實現。
(4)接口中的方法默認都是public abstract的,實現類中必須使用public修飾。
(5)接口中的全部方法都必須在實現類(抽象類除外)中實現。
(6)接口中的變量默認爲public static final的。
(7)一個類能夠實現多個接口。
3、應用場景
1)抽象類體現的是「is a」的關係,若是某一些類的實現有共通之處,則能夠抽象出來一個抽象類,讓抽象類實現共通的代碼,而個性化的方法則由各個子類去實現。
2)接口體現的是「like a」的關係,表現的是不一樣類對象在行爲上的抽象。好比飛機和鳥都會飛,能夠抽離出飛的接口,但他們非同類。
3)在軟件設計中,當你須要接口與實現分離,封裝變化的時候,面向接口編程顯得尤其重要。
好比Ioc思想,客戶端不關心你具體是什麼類,具體對象由容器來注入。
再好比兩個系統交互,良好的設計是雙方提供接口,不關心內部實現,減小耦合性的同時,封裝了變化。
不少設計原則、設計思想以及設計模式都體現出面向接口編程的重要性:開閉原則,接口隔離,依賴倒置,適配器模式等等。
關注老薑談技術,微信號:helojava,或者掃描下面二維碼。
每日一帖,技術雞湯。