Java 接口扩展问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/616684/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java interface extends questions
提问by Malachi
I have to implement an RMI server which will be a front end for two other RMI services. So I decided a logical thing to do would be to have the interface for this implement the interfaces for the other two services.
我必须实现一个 RMI 服务器,它将成为其他两个 RMI 服务的前端。所以我决定做一个合乎逻辑的事情是让这个接口实现其他两个服务的接口。
public interface FrontEndServer extends Remote, BookServer, StudentServer
{
// Block empty so far
}
However there is a method on the StudentServer
但是 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;
I would like the FrontEndServer
to also throw a BookNotFoundException
as this service will also validate if the book actually exists before attempting to add the details in.
我希望FrontEndServer
也抛出一个,BookNotFoundException
因为此服务还将在尝试添加详细信息之前验证这本书是否确实存在。
Is this possible or is my design idea completely off and this is actually a bad design idea as if the other interfaces change and all? And will I be better of writing the method signatures for all the methods inside the FrontEndServer
?
这是可能的,还是我的设计理念完全偏离了,这实际上是一个糟糕的设计理念,就好像其他界面发生了变化一样?我会更好地为 . 中的所有方法编写方法签名FrontEndServer
吗?
采纳答案by cletus
If you extend an interface (the same applies if you implement an interface), you can't override a method and have it throw morechecked exceptions than the original. You can it throw the same or less but not more.
如果你扩展一个接口(如果你实现一个接口同样适用),你不能覆盖一个方法并让它比原始方法抛出更多的检查异常。你可以抛出相同或更少但不能更多。
Think about it:
想想看:
interface A {
void foo();
}
interface B extends A {
void foo() throws IOException;
}
A a = new B() { ... }
a.foo();
would potentially throw an IOException but you'd have no way of knowing. That's why you can't do it.
可能会抛出 IOException 但您无法知道。这就是为什么你不能这样做。
This of course is perfectly acceptable:
这当然是完全可以接受的:
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
}
Your BookNotFoundException
could however extend RuntimeException
or RemoteException
. Not sure that's a good approach however.
BookNotFoundException
但是,您可以扩展RuntimeException
或RemoteException
. 然而,不确定这是一个好方法。
回答by Rob Di Marco
It is theoretically possible if BookNotFoundException extends RemoteExcepiton.
如果 BookNotFoundException 扩展 RemoteExcepiton,理论上是可能的。
However, I assume that you do not have control over the StudentServer interface. It appears that the intent of that interface is to not throw a BookNotFoundException. While I can understand why you want to, the interface doesn't seem to encourage that.
但是,我假设您无法控制 StudentServer 接口。该接口的意图似乎是不抛出 BookNotFoundException。虽然我可以理解您为什么要这样做,但界面似乎并不鼓励这样做。
回答by Eric Petroelje
A few ideas for you:
给你一些想法:
Declare the addBookToStudent method in the interface to throw a BookNotFoundException. Even though the StudentServer might never actually throw the exception, that doesn't mean you can't put it in the interface anyways.
You could create a new exception - ObjectNotFoundException and have BookNotFoundException and StudentNotFoundException inherit from there, then declare addBookToStudent to throw an ObjectNotFoundException.
What I would probably do in "real life" - have the StudentServer talk to the BookServer to validate the book id and throw the exception itself, rather than doing that check in the FrontEndServer. Especially if the StudentServer would actually be used directly by anything other than the FrontEndServer.
在接口中声明 addBookToStudent 方法以抛出 BookNotFoundException。尽管 StudentServer 可能永远不会真正抛出异常,但这并不意味着您无论如何都不能将其放入接口中。
您可以创建一个新异常 - ObjectNotFoundException 并从那里继承 BookNotFoundException 和 StudentNotFoundException,然后声明 addBookToStudent 以抛出 ObjectNotFoundException。
我在“现实生活”中可能会做的事情 - 让 StudentServer 与 BookServer 对话以验证书本 ID 并抛出异常本身,而不是在 FrontEndServer 中进行检查。特别是如果 StudentServer 实际上会被 FrontEndServer 以外的任何东西直接使用。
回答by Kam
I would suggest you attempt to separate your exposed API from the API's used to implement your functionality. My guess is that the purpose of front ending of the RMI services is to provide seperation and stability from the calling application.
我建议您尝试将公开的 API 与用于实现功能的 API 分开。我的猜测是 RMI 服务前端的目的是提供与调用应用程序的分离和稳定性。
With that I would suggest that you:
有了这个,我建议你:
- Write the API you want to expose
- Write implementations that bridge between your API and back-end services
- 编写要公开的 API
- 编写实现 API 和后端服务之间的桥梁
回答by DefLog
Exceptions are thrown by methods not interfaces or classes. So if there is a method in the BookServer
interface it could throw you exception when you add it to the interface.
异常是由方法而不是接口或类抛出的。因此,如果BookServer
接口中有一个方法,当您将其添加到接口时,它可能会抛出异常。
If you are thinking of adding the exception to the addBookToStudent
method in the FrontEndServer
interface, the answer is no it is not possible. Overridden methods in classes and interfaces may only narrow the exception or remove it completely but not add new exceptions.
如果您正在考虑向接口中的addBookToStudent
方法添加异常FrontEndServer
,答案是否定的,这是不可能的。类和接口中的重写方法可能只会缩小异常范围或完全删除它,而不会添加新的异常。
If you think about it, you see that this is logical. Your FrontEndServer
could be used as a BookServer by some code. The code during compilation expects the exceptions defined in the BookServer. Then during runtime suddenly an exception is throw by the BookServer that is not defined in the BookServer interface. If that piece of code only knows the BookException is unexpected, there are no catches or throws statements to deal with it.
如果你仔细想想,你会发现这是合乎逻辑的。您FrontEndServer
可以通过某些代码用作 BookServer。编译期间的代码需要 BookServer 中定义的异常。然后在运行时突然一个异常被 BookServer 接口中未定义的 BookServer 抛出。如果那段代码只知道 BookException 是意外的,则没有 catch 或 throws 语句来处理它。
回答by erickson
What good does a single type that extends both of these interfaces? Do you lose anything when a client depends on two distinct objects?
扩展这两个接口的单一类型有什么好处?当客户端依赖于两个不同的对象时,您会丢失任何东西吗?
Overuse of inheritance is a common beginner mistake, because "inheritance" is one of the notable traits of object-oriented programming. However, in most cases, composition is a better choice. In this case, why not have two separate services? Then, adding CafeteriaService
and DormitoryService
later doesn't impact any existing interfaces.
过度使用继承是初学者常见的错误,因为“继承”是面向对象编程的显着特征之一。但是,在大多数情况下,组合是更好的选择。在这种情况下,为什么不拥有两个独立的服务?然后,添加CafeteriaService
和DormitoryService
以后不会影响任何现有的接口。
With regard to the design, the addBookToStudent
method would benefit from being able to throw BookNotFoundException
. Interfaces are brittle, in the sense that changing them in any way breaks a lot of code. You have to be very careful in their initial design. For example, BookNotFoundException
is probably to specific; couldn't there exist a variety of exceptions that would prevent "adding" a book to a student? (I'm guessing that students are checking books out of a lending library.) For example: CheckOutLimitExceededException
, UnpaidFinePendingException
, AdultLiteraturePermissionException
, etc.
关于设计,该addBookToStudent
方法将受益于能够 throw BookNotFoundException
。接口是脆弱的,从某种意义上说,以任何方式改变它们都会破坏很多代码。在他们的初始设计中你必须非常小心。例如,BookNotFoundException
可能是特定的;难道不能存在各种阻止“添加”一本书给学生的例外情况吗?(我猜的学生检查出的书籍,借阅图书馆的。)例如:CheckOutLimitExceededException
,UnpaidFinePendingException
,AdultLiteraturePermissionException
等。
Think carefully about the types of checked-exceptions that might be appropriate for the level of abstraction when designing interfaces, because they are hard to change later.
在设计接口时仔细考虑可能适合抽象级别的已检查异常类型,因为它们以后很难更改。