Java接口扩展了问题

时间:2009-03-05 21:24:32

标签: java interface

我必须实现一个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

中的所有方法编写方法签名

6 个答案:

答案 0 :(得分:15)

如果扩展接口(如果实现接口,则同样适用),您不能覆盖方法并使其抛出更多检查的异常而不是原始方法。你可以扔掉相同或更少,但不能更多。

想一想:

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可以延长RuntimeExceptionRemoteException。但不确定这是一个好方法。

答案 1 :(得分:5)

扩展这两种接口的单一类型有什么用处?当客户依赖于两个不同的对象时,你会失去什么吗?

过度使用继承是一个常见的初学者错误,因为“继承”是面向对象编程的一个显着特征。但是,在大多数情况下,成分是更好的选择。在这种情况下,为什么不提供两个单独的服务?然后,稍后添加CafeteriaServiceDormitoryService不会影响任何现有接口。

关于设计,addBookToStudent方法可以从投掷BookNotFoundException中受益。接口是脆弱的,在某种意义上,改变它们会破坏很多代码。你必须在他们的初始设计中非常小心。例如,BookNotFoundException可能具体;难道不存在各种例外情况会妨碍向学生“添加”一本书吗? (我猜测学生正在借阅借阅图书馆。)例如:CheckOutLimitExceededExceptionUnpaidFinePendingExceptionAdultLiteraturePermissionException等。

在设计接口时要仔细考虑可能适合抽象级别的checked-exceptions的类型,因为它们以后很难改变。

答案 2 :(得分:2)

为您提供一些想法:

  1. 在接口中声明addBookToStudent方法以抛出BookNotFoundException。即使StudentServer可能永远不会抛出异常,但这并不意味着你无法将它放在界面中。

  2. 您可以创建一个新的异常 - ObjectNotFoundException,并从那里继承BookNotFoundException和StudentNotFoundException,然后声明addBookToStudent以抛出ObjectNotFoundException。

  3. 我可能会在“现实生活中”做些什么 - 让StudentServer与BookServer交谈以验证书籍ID并抛出异常本身,而不是在FrontEndServer中进行检查。特别是如果StudentServer实际上直接被FrontEndServer以外的任何东西使用。

答案 3 :(得分:2)

我建议您尝试将公开的API与用于实现功能的API分开。我的猜测是,RMI服务前端的目的是为调用应用程序提供分离和稳定性。

我会建议你:

  • 编写您要公开的API
  • 编写在API和后端服务之间架起桥梁的实现

答案 4 :(得分:1)

理论上,BookNotFoundException可以扩展RemoteExcepiton。

但是,我假设您无法控制StudentServer接口。看来该接口的意图是不抛出BookNotFoundException。虽然我可以理解你想要的原因,但界面似乎并不鼓励这样做。

答案 5 :(得分:1)

方法而不是接口或类抛出异常。因此,如果BookServer接口中有一个方法,当您将其添加到接口时,它可能会引发异常。

如果您正考虑在addBookToStudent界面中为FrontEndServer方法添加例外,那么答案是否定的。类和接口中的重写方法可能只会缩小异常或完全删除它,但不会添加新的异常。

如果你仔细想想,你会发现这是合乎逻辑的。某些代码可以将FrontEndServer用作BookServer。编译期间的代码需要BookServer中定义的异常。然后在运行时突然发生BookServer抛出异常,而BookServer接口中未定义异常。如果该段代码只知道BookException是意外的,则没有catches或throws语句来处理它。