java - 必须实现默认接口(interface)方法?

标签 java java-8 default-method

这是一个显示我的问题的简化示例:

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");
    }
}

SingleTask 中,我提供了 getsize 方法的实现,它们是 AbstractList 中唯一的抽象方法>。但是,当我编译 MyTask 时,我仍然会遇到如下错误:

The type MyTask must implement the inherited abstract method AbstractCollection.size()

MyTask.java:3: error: MyTask is not abstract and does not override abstract method get(int) in AbstractList

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

所以我有两个问题:

  1. 为什么会出现这些错误?我期待它能够识别默认实现。
  2. 如果它不应该那样工作,那么在 MyTask 中使用这两个方法而不复制整个代码的最简单方法是什么?

最佳答案

强制 SingleTask 实现者也实现 List 的所有方法不是很优雅,并且默认方法并不意味着用于定义类似特征的实体,您的 SingleTask 界面看起来像这样。

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

这正是这里发生的事情:因为 AbstractList 明确声明 get()size()abstract,这意味着 SingleTask 将继承它们,而不是您在 super 接口(interface)中可能拥有的默认实现。

JLS 8.4.8 :

A class C inherits from its direct superclass and direct superinterfaces all abstract and default (§9.4) methods m for which all of the following are true:

...

  • No concrete method inherited by C from its direct superclass has a signature that is a subsignature of the signature of 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,因此不能扩展任何其他东西,从好的方面来说,尽管它们不需要处理同样是 List 的任务,他们只需要实现run()

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

关于java - 必须实现默认接口(interface)方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35770017/

相关文章:

java - 为什么 postgresql 使用错误版本的驱动程序?

eclipse - 如何使用 Gradle 在 Gluon 项目中设置 JUnit 测试

java - 调用父类(super class)中重写的默认接口(interface)方法

java-8 - 默认 ForkJoinPool 执行器花费很长时间

java - 从 HashMap 导出 afterNodeAccess

java - 防止继承包外的接口(interface)

locking - 为什么 Java 8 没有在 `withLock` 接口(interface)中添加 `java.util.concurrent.locks.Lock` 默认方法?

java - 垂直拆分 Android 布局向两侧添加重力以使对象居中

java - KAFKA 与现代内存内存数据网格 (IMDG) 相比

java - 运行Java游戏时出现线程错误