具有包访问的抽象方法的继承

Inheritance of abstract methods with package access

根据 JLS 的“8.1.1.1”部分,我们有:

A class 如果满足以下任一条件,则 C 具有抽象方法:

• C 的任何成员方法 (§8.2) - 声明的或继承的 - 是 摘要.

• C 的任何 superclasses 都有一个声明为包访问的抽象方法, 并且不存在覆盖 C 或 C 抽象方法的方法 C

的超级class

有趣的是,为什么我们这里有第二种选择。特别是,为什么我们正好有 "package access"。 "public" 或 "protected" 方法呢?

这可能的意思是protectedpublic也是提供包访问的声明。 private 方法不是,它们也不能是抽象的。

从最私密到最开放的顺序,java 修饰符依次为:

  • 私人
  • 套餐
  • 受保护
  • public

子 class 无法继承另一个包中父 class 的包方法。因此,根据规则 1,从这样的父对象继承的 class 将不是抽象的。因此,第二条规则的存在是为了解决子对象 class 从抽象父对象继承并且无法提供抽象包方法的实现。

这是一种荒谬的情况,我绝不会期望在任何地方的任何程序中看到这种情况。但是必须完全指定语言,否则您可能会遇到一个奇怪的错误,该错误允许实例化具有未定义方法的 class。

是的,我认为你是对的。 第二种选择只涉及一种特殊情况: 特定的 subclass 与其 superclass.

在不同的包中

例如,

package superpackage;

public abstract class SuperFoo {
    abstract void foo();
}


package subpackage;

import superpackage.SuperFoo;

public abstract class SubFoo extends SuperFoo {}

请注意这个class应该声明为抽象的,否则我们会出现编译错误。

在这种特殊情况下,我们没有继承所需的 "inheritance of foo method" SubFoo class 与 SuperFoo 在同一个包中。 有关详细信息,请参阅 JLS 中的第 8.4.8 节。

尽管如此,这个 class 仍然包含 "foo" 方法(根据定义),因此应该用抽象关键字标记。

此外,我们可以通过属于 "superpackage" 包的另一个具体 class 来扩展我们的 SubFoo class。

例如,

package subclass;

import subpackage.SubFoo;

public class SecondSubFoo extends SubFoo {
    @Override
    void foo() {}
}

注:

1) 事实是 public 和 protected 方法属于第一项定义,因为它们是继承的,不需要第二项定义。

2) 包访问方法如果在同一个包中,也属于第一项定义,因此它们也不需要第二项定义。

3) 另一方面,其他包中的包访问方法不属于定义的第一项,因为它们不是继承的(参见JSL 8.4.8节抽象方法继承的定义) 因此它们是定义的第二项。