具有包访问的抽象方法的继承
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" 方法呢?
这可能的意思是protected
和public
也是提供包访问的声明。 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节抽象方法继承的定义) 因此它们是定义的第二项。
根据 JLS 的“8.1.1.1”部分,我们有:
A class 如果满足以下任一条件,则 C 具有抽象方法:
• C 的任何成员方法 (§8.2) - 声明的或继承的 - 是 摘要.
• C 的任何 superclasses 都有一个声明为包访问的抽象方法, 并且不存在覆盖 C 或 C 抽象方法的方法 C
的超级class有趣的是,为什么我们这里有第二种选择。特别是,为什么我们正好有 "package access"。 "public" 或 "protected" 方法呢?
这可能的意思是protected
和public
也是提供包访问的声明。 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节抽象方法继承的定义) 因此它们是定义的第二项。