第四章 系統軟體介紹
4.3. 介面(I NTERFACE )機制說明
在前面已經提過繼承是物件導向語言中的重要特性之後,這邊還要介紹另一項特性-介 面,而在說明實作部分之前,我們這邊一樣也先對介面的功能以及意義做說明,最後再接著 描述這些機制在我們平台上實作的方式。
介面的宣告像是在定義一個東西應有的行為,所以介面本身只有行為名稱,卻沒有描述 行為的詳細動作,若是某個物件型別實做了一個介面,則該物件型別必須把介面的所有方法 都實作出來,這麼的規範也表示任何實做了某介面的物件型別,我們可確信其必具有介面應 有的方法,就算方法內容的動作大不相同,我們仍然可以呼叫,而在使用上,因為在 JAVA 語言本身並不提供多重繼承的功能,所以一般也會透過介面的使用上來達到多重繼承的效果,
因為 JAVA 支援一次實作多個介面,就像是同時繼承多個抽象物件型別(實際上這是 C++中 多重繼承的一個實際運用方式),以下(圖 24)是一個介面的例子,我定義了一個 Interface 叫 phone,他必具備一個叫 dial 的方法,但是在介面裡並不會詳述要怎麼動作,而右邊是實 做了這個介面的物件型別,在這物件型別裡面就必須把介面裡的方法完整的描述出來。
圖24. 介面與實作其方法的物件型別例子
Interface: phone
public interface phone { public void dial();
}
Class: nokia
public class nokia implements phone{
public void dial(){
… };
}
法(invokespecial、invokevirtual、invokestatic)會直接連結到屬於該物件型別方法的參考資 訊(reference data)。
圖25. 透過呼叫介面方法的方式呼叫實作其的物件型別方法
上圖 25 是一個實際呼叫介面方法的例子,左半邊是一個程式片段,接續前段的例子,這 邊另外又多加了個物件型別,也同樣實做了 phone 這個介面,這邊 n3310 與 T28 是兩個具有 相同介面屬性的物件,而他們真正的身分是個別是 nokia 與 ericsson,接下來呼叫使用該介面 裡定義的行為 dial,所以就透過了 Invokeinterface dial 來呼叫,然而因為 n3310 跟 T28 是不同 身分的物件,所以在 Java 雖然使用同樣的 byte code,最後卻會呼叫到的 dial 其 code 會不同。
Code fragment
…
phone n3310= new nokia();
n3310.dial();
phone T28= new ericsson();
T28.dial();
…
Class: nokia
public class nokia implements phone{
public void dial(){
… };
}
Class: Ericsson
public class ericsson implements phone{
public void dial(){
… };
} Invokeinterface
Invokeinterface
是來自於父物件型別,而在語法中我們可以透過父物件型別實作的介面來呼叫子物件型別的 方法,這邊子物件型別的方法定義包含子物件型別有覆寫(over write)的方法或是僅繼承至 父物件型別,當子物件型別未覆寫其繼承的方法時,若不增加此欄位的話,我們當
Invokeinterface 時會在 method list 上找不到屬於子物件型別 Class ID 的方法,所以之後我們在 解析一個物件型別時,會將它每個實作的方法加到其有實作介面的 method list 上面,新的資 料結構如圖 26 所示。
圖26. 一般物件型別與介面在方法參照資料上的差異
Class ID Method Offset
Cross reference table
Class [X]
: :
Interface Info IsInterface (1 or 0) Interface Count Interface List
0 int short array
Method Info Method Name Reference Data
Method[x] char array ptr
: :
On-chip memory (BRAM) in JAIP
Cross reference table
Class [X]
: :
Interface Info IsInterface (1 or 0) Interface Count Interface List
1 int short array
Method Info Method Name Reference Data
Method[x] char array ptr
: :
Class ID
Class ID Method Offset ptr
Class ID
Class ID Method Offset ptr
在解析子物件型別實作介面前,會先完成其父物件型別及其實作介面的解析,可以順利建立 完整的介面資訊。
圖27. 在物件型別解析的流程中實作介面的機制 Parse constant pool
Check this class’s parent class has been parsed or not.
Add interface info from parent class No
Yes
Parse parent class
Add interface info from own interface Check the interface
implemented by this class has been parsed or
not. Yes
No
Parse interface
Maintain interface’s method list
Continue parse this class Continue parse this class