【问题标题】:Implementing a method which is declared in an interface and parent class实现在接口和父类中声明的方法
【发布时间】:2015-10-21 19:42:14
【问题描述】:

我这里有点两难,

说我有课

public class Child extends Parent implements Interface{
 public static void main(String[] args){
  Child child = new Child();
   child.methodOne(); } }

在哪里

abstract class Parent {

public void methodOne()  {
    System.out.print("cannot fly ");
}}

interface Interface {
public abstract void methodOne() throws Exception;}

这个结构没有编译错误

如果我这样做了

abstract class Parent {

public void methodOne() throws Exception {
    System.out.print("cannot fly ");
}}

interface Interface {
public abstract void methodOne(); }

两个编译错误上升说

Exception Exception in throws clause of Parent.methodOne() is not compatible with Interface.methodOne()

Unhandled exception type Exception

要求在main 方法中添加throwstry/catch

为什么会这样?

【问题讨论】:

  • 如果在两个地方都添加 throws 子句会发生什么?
  • 我认为对发生的事情有很多解释。总之,您从 Parent 继承了一个部分匹配 Interface 签名的方法。要解决这个问题,只需覆盖该方法并使其不引发检查异常。例如try { super.methodOne(); } catch (Exception e) { throw new RuntimeException(e); }

标签: java inheritance


【解决方案1】:

每次你实现一个接口(或从父类重写一个方法,同样的事情),你需要尊重该接口的约定。遵守约定意味着你不能抛出比接口声明更多的异常。

在这两种情况下,Interface 是契约,Parent 是实现(通过在类 Child 中发生的两者之间的“绑定”)。

在第一种情况下,界面说methodOne()允许抛出异常,但不是必须的。您在Parent 中的实际实现不会抛出任何东西,因此它是合同的一个子集并且很好。

在第二种情况下,接口说methodOne() 不会抛出任何东西(*),因此任何实现都不允许抛出任何异常。但是Parent中的实现要求允许抛出,与接口契约不兼容;因此编译器错误。

另请注意,在第二种情况下,您可以很好地用空的throws 声明覆盖Child 中的methodOne(),以便签名符合接口协定。然后您可以调用super.methodOne() 并将Exception 重新包装为RuntimeException(例如)。

顺便说一句:

  • 如果你用相同的方法签名实现多个接口,实现只能抛出所有接口的throws声明的交集;
  • 您不需要在接口中使用abstract 关键字,因为接口中的方法声明本质上总是抽象的。

(*) 当然 RuntimeException 除外。

【讨论】:

  • 感谢您的帮助。
【解决方案2】:

当你这样做时,

public class Child  extends Parent implements Interface
  • 父类正在实现接口。
  • Parent 类中的methodOne 成为被覆盖的方法。
  • 正在扩展父类的子类,没有看到此异常。

但是,当您在父 class' 方法中显式抛出 exception 时,您必须在从子对象进行调用时处理该异常。

【讨论】:

    【解决方案3】:

    throws 声明不是接口InterfacemethodOne() 合约的一部分。

    当你实现一个接口时,你必须实现你的方法契约,如果接口有一个throws 声明,你可以在不添加throws 声明的情况下做到这一点。

    但是,您不能添加 Interface 合同中未规定的功能。

    您可以通过修改您的 main 方法来修复另一个错误,同时抛出 Exception

     public static void main(String[] args) throws Exception {
      Child child = new Child();
       child.methodOne(); 
     }
    

    或将methodOne() 调用包围在try-catch 块中:

     public static void main(String[] args) throws Exception {
      Child child = new Child();
       try{
           child.methodOne(); 
       }catch(Exception e){
          //do something to handle exception i.e. System.out.println(e.getMessage());
       }
     }
    

    补充阅读:Java interface throws an exception but interface implementation does not throw an exception?

    摘录:

    实现和扩展的一般规则是您可以使您的新类或接口“限制更少”,但不能“限制更多”。如果您将处理异常的要求视为限制,则不声明异常的实现限制较少。任何编写接口代码的人都不会在您的课程中遇到麻烦。

    【讨论】:

    • 我不明白。为什么它首先对他有用?
    • 哦等等,是不是因为方法首先是类的一部分。所以从现在开始,谁想使用那个方法,就必须遵守类设定的约定。成员可以添加到合同中,但不能从中删除。
    • @AbtPst 你几乎有了这个概念,只是有点混淆了。成员可以选择不包含诸如 throws 声明之类的内容,但他们不能添加未在接口中声明的声明。没有成员显式修改接口。
    猜你喜欢
    • 2014-05-09
    • 2012-09-01
    • 2015-07-19
    • 2021-03-24
    • 1970-01-01
    • 2014-02-02
    • 2012-09-22
    • 1970-01-01
    • 2013-09-23
    相关资源
    最近更新 更多