【问题标题】:Interface does not see concrete implementation接口看不到具体实现
【发布时间】:2015-01-30 22:41:11
【问题描述】:

我有

ISomeInterface

public interface ISomeInterface{
    public void myMethod();
} 

抽象类

public abstract class AbstractClass implements ISomeInterface{

    public void myMethod(){
    //...here goes implemetations
    }
}

具体类

public class ConcreteClass extends AbstractClass {
    //...
}

编译器打印的ConcreteClass 不是抽象的,并且不会覆盖ISomeInterface 中的抽象方法myMethod

这个想法是给一个抽象类实现,然后在扩展它的类中继承它。 我认为ConcreteClass 应该得到实现形式AbstractClass,因为它正在扩展它。对?怎么了?

更新

直到现在我才注意到method 是错误的,它必须是myMethod。无论如何,同样的错误。

更新2

问题是在 AbstractClass 中,它们的方法名称正确但签名不正确。根据界面更改后问题解决了:)

【问题讨论】:

  • AbstractClass 中对myMethod 使用@Override 注释有助于识别此错误。
  • 这很奇怪。您使用的是哪个编译器?使用Oracle官方编译器,编译无误
  • 你现在改变了你的问题并说如果你在接口和类中都有相同的方法名,你会得到同样的错误。如果你有相同的方法名和相同的大小写敏感,你不会得到关于它没有在 ConcreteClass 中实现的错误。仔细检查您对代码的更新。

标签: java


【解决方案1】:

AbstractClass 中,您正在创建一个方法myMethod(),但您的接口方法method() 没有在ConcreteClass 中实现。名称不同。

【讨论】:

    【解决方案2】:

    假设您的示例代码是完整的,您需要在您的界面中实现method。在AbstractClass 中,您将其称为myMethod

    您可以在任何覆盖方法上使用@Override 注释。这将告诉您是否使用了错误的参数类型、方法名称或不兼容的返回类型(参数和返回类型不必相同;例如,它们可以是 covariant)。

    此外,在 Java 中,我们不倾向于在接口名称前加上 I(与 C# 中的约定不同)。您的界面通常称为SomeInterface 而不是ISomeInterface

    此外,接口is implicit 上的方法上的public,因此您可以将其省略。如果您确实包含它,您可能应该包含 abstract 以及包含所有隐式修饰符。

    更新后的代码示例是:

    public interface SomeInterface{
      void method();
    } 
    
    public abstract class AbstractClass implements SomeInterface {
      @Override
      public void method(){
          //...here goes implemetations
      }
    }
    

    【讨论】:

    • 接口名称是通用约定,不是要求。
    • @Kon。我没有说这是一个要求,我说的是“倾向于”。
    【解决方案3】:

    可能重写了错误的方法。发生的情况是,您可能正试图覆盖抽象类中的方法,但您实际上所做的只是用新名称定义一个新方法。在接口中,方法名为method,但在您的抽象类中,您的方法名为myMethod

    所以,看看这个:

    public abstract class AbstractClass implements ISomeInterface{
    
        // Not the same name as in the interface
        public void myMethod(){
            //...here goes implemetations
        }
    }
    

    为了解决它,只需将子类中的方法名称更改为正确的名称即可。

    public abstract class AbstractClass implements ISomeInterface{
        // Now you have the correct name and inheritance will
        // work as expected
        @Override
        public void method(){
            //...here goes implemetations
        }
    }
    

    这也是解释@Override 注释的完美案例;)

    当覆盖一个方法时,你可能想要使用@Override 注解来指示编译器你打算覆盖超类中的一个方法。如果由于某种原因,编译器检测到某个超类中不存在该方法,则会产生错误。

    当您使用注释@Override 声明方法时,被覆盖的方法必须与接口方法(或超类方法)的签名相匹配。阅读更多关于@Overridein the Oracle Docs的信息。

    而且,如果您不想在抽象类中重写名为 method 的方法,您只需将该方法添加到具体类中,如下所示:

    public class ConcreteClass extends AbstractClass {
        // Now we are implementing the correct method from the interface
        // If not, there will be a compiler error.
        @Override
        public void method() {
    
        }
        //...
    }
    

    在一个可能相关的旁注中:方法可以具有相同的名称,但具有不同的参数列表。这称为重载(或重载方法),您可以在this article 中了解更多信息。

    编辑: 由于 OP 使用 Java 5 this question 可能会很有趣。 @Override 注释在 Java 5 和 Java 6 之间发生了变化。在 Java 5 中,当实现接口中的方法时,不允许使用 @Override 注释,只允许在重写方法时使用来自超类。

    【讨论】:

    • 所以method() 必须 在 AbstractClass 中被覆盖以实现接口?它在没有@Override 注释的情况下编译
    • @RCola 否。与超类型签名不匹配的方法如果具有该注解将无法编译。
    • @RCola,谢谢 Elliot。如果您添加@Override,您将保证您正在实现的方法实际上覆盖了超类或接口方法(即具有相同签名的方法)。
    • @RCola,进一步:如果您将 any method 添加到具有不同签名的抽象类中,则它是 not 覆盖。签名基于方法名称、参数、异常列表等。这就是为什么添加@Override 是一个好主意(如果您正在覆盖)。然后你知道你实际上覆盖了预期的方法。
    • @RCola,如果是这样的话 - 删除它;)只需确保该方法具有相同的签名。这在 Java 5 和 Java 6 之间发生了变化(阅读更多关于它的信息 here)。更好的是,如果可能的话升级到 Java 6。
    【解决方案4】:

    你的接口定义

    public void method();
    

    但是你的抽象类有

    public void myMethod(){
        //...here goes implemetations
    }
    

    这不一样!添加 Override 注释以在编译时捕获此类问题。

    @Override
    public void myMethod(){ // <-- compile error.
        //...here goes implemetations
    }
    

    来自链接的 Javadoc,

    表示方法声明旨在覆盖超类型中的方法声明。

    【讨论】:

    • 为什么这是一个“覆盖”问题?他从抽象内部的接口实现方法,而不是覆盖超类的方法。
    • @tgm1024 因为接口中的方法在抽象类中有不同的名称。因此,抽象类没有覆盖超类型(接口)方法。添加注释会在编译时捕获该错误。正如我在回答中所说的那样。
    • @tgm1024 使用双反引号。 @Override.
    • 没有。因为抽象类可以仅仅实现方法。被覆盖的是接口。
    • 我只是仔细检查了一遍。 @override 确实包括实现一个接口。你是正确的艾略特。上面列出的链接 javadoc 说“表明方法声明旨在覆盖超类型中的方法声明。”我认为没有应用接口。
    【解决方案5】:

    我注意到的第一件事是您的方法在接口和抽象类中的名称不同。

    【讨论】:

      猜你喜欢
      • 2021-07-10
      • 2019-02-26
      • 1970-01-01
      • 2013-06-03
      • 2016-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多