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

Java 具有包访问的抽象方法的继承,java,inheritance,abstract,Java,Inheritance,Abstract,根据JLS第8.1.1.1节,我们有: 如果满足以下任一条件,则类C具有抽象方法: •C的任何成员方法(§8.2)——声明的或继承的——都是 抽象的 •C的任何超类都有一个用包访问声明的抽象方法, 并且不存在重写C或中的抽象方法的方法 C的超类 有趣的是,为什么我们有第二个选择呢。特别是,为什么我们有确切的“包访问”。那么“public”或“protected”方法呢?这可能意味着protected和public也是提供包访问的声明私有方法不是,它们也不能是抽象的。从最私有到最开放的顺序,jav

根据JLS第8.1.1.1节,我们有:

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

•C的任何成员方法(§8.2)——声明的或继承的——都是 抽象的

•C的任何超类都有一个用包访问声明的抽象方法, 并且不存在重写C或中的抽象方法的方法 C的超类


有趣的是,为什么我们有第二个选择呢。特别是,为什么我们有确切的“包访问”。那么“public”或“protected”方法呢?

这可能意味着
protected
public
也是提供包访问的声明<代码>私有方法不是,它们也不能是抽象的。

从最私有到最开放的顺序,java修饰符是:

  • 私人的
  • 包装
  • 保护
  • 公开的
子类不能继承另一个包中父类的包方法。因此,根据规则1,从这样的父类继承的类不会是抽象的。因此,第二条规则用于解决子类继承自抽象父类且无法提供抽象包方法的实现的情况


这是一个荒谬的情况,我永远不会期望在任何地方的任何节目中看到这一点。但是必须完全指定语言,否则可能会出现一个奇怪的错误,允许实例化具有未定义方法的类。

是的,我认为你是对的。 第二种选择只涉及一种特殊情况: 特定的子类与其超类位于不同的包中

比如说,

package superpackage;

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


package subpackage;

import superpackage.SuperFoo;

public abstract class SubFoo extends SuperFoo {}
package subclass;

import subpackage.SubFoo;

public class SecondSubFoo extends SubFoo {
    @Override
    void foo() {}
}
请注意,这个类应该声明为抽象类,否则我们就有编译错误

在这种特殊情况下,我们没有继承所需的“foo方法的继承” 该Subfo类必须与SuperFoo位于同一个包中。 有关更多详细信息,请参见JLS中的第8.4.8节

尽管如此,这个类仍然包含“foo”方法(根据定义),因此应该用abstract关键字标记

此外,我们可以通过属于“superpackage”包的另一个具体类来扩展Subfo类

比如说,

package superpackage;

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


package subpackage;

import superpackage.SuperFoo;

public abstract class SubFoo extends SuperFoo {}
package subclass;

import subpackage.SubFoo;

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

1) 事实上,公共和受保护的方法在继承时属于第一项定义,它们不需要第二项定义

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


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

基本上是说,在为所有抽象方法(类中显式的方法或父类中隐式的方法)提供具体实现之前,类是抽象的。记住:“包范围”是指您没有指定“public”或“protected”或“private”;它在包内的任何位置都可见,在包外不可见。