当前位置: 首页 > 知识库问答 >
问题:

必须实现默认接口方法?

颜奇希
2023-03-14

下面是一个简单的例子,展示了我的问题:

import java.util.List;

public interface SingleTask extends List<Runnable>, Runnable {
    default Runnable get(final int x) {
        if (x != 0) {
            throw new IndexOutOfBoundsException();
        }
        return this;
    }

    default int size() {
        return 1;
    }
}

import java.util.AbstractList;

public class MyTask extends AbstractList<Runnable> implements SingleTask {
    @Override
    public void run() {
        System.out.println("hello");
    }
}

SingleWG中,我提供了方法getsize的实现,这是来自AbstractList的唯一抽象方法。但是,当我编译MyWork时,我仍然会遇到以下错误:

类型MyWork必须实现继承的抽象方法AbstractCollection.size()

或者

我的任务。java:3:错误:MyTask不是抽象的,并且不重写AbstractList中的抽象方法get(int)

(取决于编译器)。当然,我使用的是java 8。

所以我有两个问题:

  1. 为什么我得到这些错误?我希望它能识别默认的实现。
  2. 如果它不应该这样工作,那么在不复制整个代码的情况下,在MyWork中使用这两个方法的最简单方法是什么?

共有2个答案

林炫明
2023-03-14
  1. 为什么我会犯这些错误?我希望它能够识别默认的实现

我认为@biziclop在他的回答中正确地涵盖了这一点。简而言之,由于AbstractListget(int)size()方法声明为抽象方法,因此它们优先于SingleTask中的默认实现。

最简单的方法是重写MyWG中的get(int)size()方法,以便它们委托给您在SingleWG接口中的默认方法:

public class MyTask extends AbstractList<Runnable> implements SingleTask {

    @Override
    public void run() {
        System.out.println("hello");
    }

    @Override
    public Runnable get(int index) {
        return SingleTask.super.get(index);
    }

    @Override
    public int size() {
        return SingleTask.super.size();
    }
}

使用这种方法,您将有点委托给SingleTask中的默认方法。我不认为这是一件坏事(至少,您不需要使用属性)。此外,编写这些方法是有意义的,这样您就可以选择提供默认实现的接口。

祁曦哲
2023-03-14

强制SingleTask实现者也实现List的所有方法不是很优雅,默认方法也不是用来定义你的SingleTask界面看起来像的特征实体。

默认方法作为特征是一个坏主意,有几个原因,最明显的一个是任何实现者都可以简单地覆盖你的默认方法,破坏你的特征。

这正是这里正在发生的事情:因为AbstractList显式声明get()size()抽象,这意味着SingleWG将继承它们,而不是您的默认实现可能有一个超级界面。

JLS 8.4.8:

类C从其直接超类和直接超接口继承所有抽象和默认(§9.4)方法m,对于这些方法m,以下所有条件均为真:

...

  • C从其直接超类继承的具体方法没有签名是m签名的子签名

考虑到所有这些,最简单的解决方案可能是:

public abstract class SingleTask extends AbstractList<Runnable> implements Runnable {
    @Override
    public final Runnable get(final int x) {
        if (x != 0) {
            throw new IndexOutOfBoundsException();
        }
        return this;
    }

    @Override
    public final int size() {
        return 1;
    }

    @Override
    public abstract void run();
}

它的缺点是您的任务必须扩展SingleTask,因此不能扩展任何其他内容,从好的方面来说,虽然它们不需要处理任务,但它们也是列表,它们只需要实现run()

但是从长远来看,我更喜欢组合而不是继承,任务只是返回一个可运行的列表,而不是它们本身。

 类似资料:
  • 本文向大家介绍Kotlin 与默认实现接口,包括了Kotlin 与默认实现接口的使用技巧和注意事项,需要的朋友参考一下 示例 Kotlin中的接口可以具有功能的默认实现: 实现此类接口的类将能够使用这些功能而无需重新实现 物产 默认实现也适用于属性获取器和设置器: 接口访问器实现不能使用后备字段 多种实现 当多个接口实现相同的功能,或者所有接口都定义一个或多个实现时,派生类需要手动解析正确的调用

  • 我遵循本指南https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods使用默认接口实现功能。我复制了一段在接口中定义默认实现的代码,然后在接口中重写它: 但它给出了一个错误和一个警告。设置为,为。为什么即使在官方文件中有描述也不起作用

  • 本文向大家介绍我们是否必须在实现Java接口的类中实现所有方法?,包括了我们是否必须在实现Java接口的类中实现所有方法?的使用技巧和注意事项,需要的朋友参考一下 是的,必须在实现接口的类中实现所有方法,直到并且除非该类被声明为抽象类。 只有两个选择- 实现接口定义的每个方法。 将该类声明为抽象类,结果迫使您在创建任何对象之前先对该类进行子类化(并实现缺少的方法)。 类不需要在接口中实现所有方法的

  • 我想避免在maven插件swagger codecen生成的接口中实现“默认”。例如,使用petstore swagger:http://petstore.swagger.io/v2/swagger.json 我用maven插件生成接口: 我生成类似PetApi的接口。具有默认方法实现的java: 我想尽量避免 有可能做到吗? 2020年3月更新: 根据新的OpenAPI工具 有一个带有的选项(已

  • 问题内容: 向所有Java专家致敬! 从Java8开始,我们可以在接口中使用默认实现(是的!)。但是,当您想从默认方法登录时会出现问题。 我有种感觉,每次我想在默认方法中记录某些内容时都调用.getLogger()是不明智的。 是的,可以在接口中定义静态变量-但这对于接口而言不是一个好习惯,而且+暴露了记录器(必须是公开的)。 我目前的解决方案: LogHolder仍然对所有人可见,这实际上没有任

  • 问题内容: 考虑以下情况, 在上面的例子中我得到以下输出这是 相当 期待。 我一直在阅读有关默认方法的信息, 尤其是 关于扩展包含默认方法的接口的信息 2 第二子弹:重新声明的默认方法,这使得它的抽象。 在上面的示例中,我有两个接口的默认方法具有相同的名称,并且当我实现这两个接口时,我只能实现对的引用。 我对此几乎没有疑问, 我怎样才能 到达 的方法 和 如果我不能比,为什么? 没有这种行为从本质