定義
介面,英文稱作interface,在軟體工程中,介面泛指供別人呼叫的方法或者函式。從這裡,我們可以體會到Java語言設計者的初衷,它是對行為的抽象。在Java中,定一個介面的形式如下:
[public] interface InterfaceName {
}
複製程式碼
介面中可以含有變數和方法。但是要注意,介面中的變數會被隱式地指定為public static final
變數(並且只能是public static final變數,用private修飾會報編譯錯誤),而方法會被隱式地指定為public abstract
方法且只能是public abstract方法(用其他關鍵字,比如private、protected、static、 final等修飾會報編譯錯誤),並且介面中所有的方法不能有具體的實現,也就是說,介面中的方法必須都是抽象方法。從這裡可以隱約看出介面和抽象類的區別,介面是一種極度抽象的型別,它比抽象類更加“抽象”,並且一般情況下不在介面中定義變數。
實現類
要讓一個類遵循某組特地的介面需要使用implements
關鍵字,具體格式如下:
[public] class ClassName implements Interface1,Interface2,[....]{
}
複製程式碼
可以看出,允許一個類遵循多個特定的介面。如果一個非抽象類遵循了某個介面,就必須實現該介面中的所有方法。對於遵循某個介面的抽象類,可以不實現該介面中的抽象方法。
一個例子
- 問題: 飛機 導彈 子彈 籃球 石頭 有什麼關係?
package com.shxt.interface_class;
public interface Flyable {
/* public static final */int MAX_SPEED = 7900;
public static final int MIN_HEIGHT = 1;
/*public abstract*/ void fly();
}
class Plane implements Flyable{
@Override
public void fly() {
System.out.println("飛機通過發動機飛");
}
}
class Man implements Flyable{
@Override
public void fly() {
System.out.println("跳起來,飛行高度最小為:"+MIN_HEIGHT+"米");
}
}
class Stone implements Flyable,Attack {
@Override
public void fly() {
System.out.println("扔出去,飛,但是需要帶有攻擊性");
}
@Override
public void attack() {
System.out.println("石頭進行攻擊");
}
}
//繼續首相介面
interface Attack{
void attack();
}
複製程式碼
為什麼需要介面?
-
介面就是比"抽象類"還"抽象"的"抽象類"(特殊的抽象類),可以更加規範的對子類進行約束.
-
核心,全面地專業地實現了:規範和具體實現的的分離
-
介面就是定義規範,解除耦合關係,第一的是一組規則,體現了現實世界中"如果你是...則必須能..."的思想.
如果你是天使,則必須能飛
如果你是汽車,則必須能跑
如果你是好人,則必須幹掉壞人
如果你是壞人,則必須欺負好人
-
介面的本質是"契約精神",就像我們人間的法律一樣,制定好後大家都必須遵守.
-
專案的具體需求是多變的,我們必須以不變應萬變才能從容開發,此處的"不變"就是"規範".因此,我們開發專案往往是面向介面程式設計
我對介面的一些總結
-
有時必須從幾個類中派生出一個子類,繼承它們所有的屬性和方法。但是,Java不支援多重繼承。有了介面,就可以得到多重繼承的效果(介面採用多繼承機制)。
-
介面(interface)是抽象方法和常量值的定義的集合。
-
從本質上講,介面是一種特殊的抽象類,這種抽象類中只包含常量和方法的定義,而沒有變數和方法的實現。
-
[關鍵]一個類可以實現多個介面,介面也可以繼承其它介面。
-
用interface關鍵字來定義。
-
介面中的所有成員變數都預設是由public static final修飾的。
-
介面中的所有方法都預設是由public abstract修飾的。
-
[關鍵]介面沒有構造器。
-
實現介面的類中必須提供介面中所有方法的具體實現內容,方可例項化。否則,仍為抽象類。
-
介面的主要用途就是被實現類實現。(面向介面程式設計)
-
與繼承關係類似,介面與實現類之間存在多型性
-
定義Java類的語法格式:先寫extends,後寫implements
<修飾符> class <類名> [extends <父類>] [implements <介面A> [,<介面B>]... ] { <declarations> } 複製程式碼
-
通過介面可以實現不相關類的相同行為,而不需要考慮這些類之間的層次關係。
-
通過介面可以指明多個類需要實現的方法,一般用於定義物件的擴張功能。
-
介面主要用來定義規範。解除耦合關係。
三.介面和抽象類之間的關係
No. | 區別點 | 抽象類 | 介面 |
---|---|---|---|
1 | 定義 | 包含一個抽象方法的類 | 抽象方法和全域性常量的集合 |
2 | 組成 | 構造方法、抽象方法、普通方法、常量、變數 | 常量、抽象方法 |
3 | 使用 | 子類繼承抽象類(extends) | 子類實現介面(implements) |
4 | 關係 | 抽象類可以實現多個介面 | 介面不能繼承抽象類,但允許繼承多個介面 |
5 | 常見設計模式 | 模板設計 | 工廠設計、代理設計 |
6 | 物件 | 都通過物件的多型性產生例項化物件 | |
7 | 侷限 | 抽象類有單繼承的侷限 | 介面沒有此侷限 |
8 | 實際 | 作為一個模板 | 是作為一個標準或是表示一種能力 |
9 | 選擇 | 如果抽象類和介面都可以使用的話,優先使用介面,因為避免單繼承的侷限 | |
10 | 特殊 | 一個抽象類中可以包含多個介面,一個介面中可以包含多個抽象類 |
在開發中,一個類不要去繼承一個已經實現好的類,要麼繼承抽象類,要麼實現介面。
四.回撥函式[鉤子]
抽象類實現
可能示例有點牽強,但是我想說的是抽象類的使用
模版設計模式
package com.shxt.abstract_demo;
public abstract class RunTimeTest {
public void getRunTime(){
//獲取當前的毫秒數 1970.1.1
long start = System.currentTimeMillis();
//測試程式碼
this.code();
long end = System.currentTimeMillis();
System.out.println(end-start+"ms");
}
public abstract void code();
}
class Code01 extends RunTimeTest{
@Override
public void code() {
for(int i=1;i<1000000;i++){
System.out.println(i);
}
}
}
class Code02 extends RunTimeTest{
@Override
public void code() {
for(int i=1;i<100;i++){
System.out.println(i);
}
}
}
複製程式碼