[英]Java interface extends questions
我必須實現一個 RMI 服務器,它將作為其他兩個 RMI 服務的前端。 所以我決定做一個合乎邏輯的事情是讓這個接口實現其他兩個服務的接口。
public interface FrontEndServer extends Remote, BookServer, StudentServer
{
// Block empty so far
}
但是 StudentServer 上有一個方法
/**
* Allows a student to borrow a book
*
* @param studentID of the student who wishes to borrow a book
* @param bookID of the book the student wishes to borrow
* @throws RemoteException
* @throws StudentNotFoundException when a student is not found in the system
*/
void addBookToStudent(int studentID, int bookID) throws RemoteException, StudentNotFoundException;
我希望FrontEndServer
也拋出一個BookNotFoundException
,因為該服務還將在嘗試添加詳細信息之前驗證這本書是否確實存在。
這是可能的還是我的設計理念完全不成立,這實際上是一個糟糕的設計理念,就好像其他接口發生了變化一樣? 我會更好地為FrontEndServer
中的所有方法編寫方法簽名嗎?
如果你擴展一個接口(如果你實現一個接口,同樣適用),你不能重寫一個方法並讓它拋出比原來更多的檢查異常。 你可以拋出相同或更少但不能更多。
想一想:
interface A {
void foo();
}
interface B extends A {
void foo() throws IOException;
}
A a = new B() { ... }
a.foo();
可能會引發 IOException 但您無法知道。 這就是為什么你不能這樣做。
這當然是完全可以接受的:
interface A {
void foo() throws IOException;
}
interface B extends A {
void foo();
}
A a = new B() { ... }
try {
a.foo();
} catch (IOException e) {
// must catch even though B.foo() won't throw one
}
但是,您的BookNotFoundException
可以擴展RuntimeException
或RemoteException
。 但是不確定這是一個好方法。
擴展這兩個接口的單一類型有什么好處? 當客戶端依賴於兩個不同的對象時,您會丟失任何東西嗎?
過度使用 inheritance 是初學者常見的錯誤,因為“繼承”是面向對象編程的顯着特征之一。 但是,在大多數情況下,組合是更好的選擇。 在這種情況下,為什么不擁有兩個獨立的服務呢? 然后,稍后添加CafeteriaService
和DormitoryService
不會影響任何現有接口。
關於設計, addBookToStudent
方法將受益於能夠拋出BookNotFoundException
。 接口很脆弱,從某種意義上說,以任何方式更改它們都會破壞大量代碼。 在他們的初始設計中你必須非常小心。 例如, BookNotFoundException
可能是特定的; 難道不能存在各種例外情況來阻止向學生“添加”一本書嗎? (我猜學生正在借閱圖書館借書。)例如: CheckOutLimitExceededException
、 UnpaidFinePendingException
、 AdultLiteraturePermissionException
等。
在設計接口時仔細考慮可能適合抽象級別的檢查異常的類型,因為它們以后很難更改。
給你一些想法:
在接口中聲明 addBookToStudent 方法拋出 BookNotFoundException。 即使 StudentServer 可能永遠不會真正拋出異常,但這並不意味着您無論如何都不能將它放在接口中。
您可以創建一個新異常 - ObjectNotFoundException 並從那里繼承 BookNotFoundException 和 StudentNotFoundException,然后聲明 addBookToStudent 以拋出 ObjectNotFoundException。
我在“現實生活”中可能會做的事情 - 讓 StudentServer 與 BookServer 對話以驗證書籍 ID 並自行拋出異常,而不是在 FrontEndServer 中進行檢查。 特別是如果 StudentServer 實際上會被 FrontEndServer 以外的任何東西直接使用。
我建議您嘗試將暴露的 API 與用於實現您的功能的 API 分開。 我的猜測是,RMI 服務前端的目的是提供與調用應用程序的分離和穩定性。
有了這個,我建議你:
如果 BookNotFoundException 擴展 RemoteExcepiton,理論上是可能的。
但是,我假設您無法控制 StudentServer 接口。 該接口的目的似乎是不拋出 BookNotFoundException。 雖然我能理解您為什么要這樣做,但界面似乎並不鼓勵這樣做。
異常是由方法而不是接口或類引發的。 因此,如果BookServer
接口中有一個方法,當您將其添加到接口時,它可能會拋出異常。
如果您正在考慮將異常添加到FrontEndServer
接口中的addBookToStudent
方法,答案是否定的,這是不可能的。 類和接口中的重寫方法只能縮小異常范圍或將其完全刪除,但不會添加新異常。
如果你仔細想想,你會發現這是合乎邏輯的。 您的FrontEndServer
可以通過某些代碼用作 BookServer。 編譯期間的代碼需要 BookServer 中定義的異常。 然后在運行時突然一個異常由 BookServer 引發,該異常未在 BookServer 接口中定義。 如果那段代碼只知道 BookException 是意外的,則沒有 catch 或 throws 語句來處理它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.