java - `Sub` 和 `Super` 中定义的私有方法,这两个方法都可以在 Sub 的 Object 上调用,那为什么私有方法说不被继承呢?
问题描述
子类不继承其父类的私有成员。但是,如果超类具有访问其私有字段的公共或受保护方法,则子类也可以使用这些方法。
[问题]
对于类关系Sub extends Super
,据了解,Oracle 文档这样说只是为了支持“只能覆盖继承的方法”这一事实,但这是一种误导性陈述,好像它似乎暗示 =>如果一个方法不是继承的,那么它就不会作为 Sub 类的对象的行为存在,如果是这样,那么它决不能在 Sub 类的对象上调用。但是 Super 类中的方法可以在 Sub 类的 Object 上调用 Super 类定义的私有方法。请参考以下几点和相关代码,并建议我的理解是否存在一些差距?
我一直把继承理解为以下3点
- 一个类
Sub
继承所有实例方法和字段(包括私有的)。 - 如果一个方法是私有的,
Super
那么它是不可见的,Sub
但这并不意味着一个对象Sub
没有该行为。
第 1 点和第 2 点的代码
public class Super{
private void privateMethod(){
System.out.println("private method defined in Super");
}
public void m(){
privateMethod();
}
}
public class Sub extends Super{
}
public void Other{
public static void main(String[] args){
Sub s = new Sub();
s.m();
}
}
我们创建了一个对象Sub
,m()
被继承Sub
,其public
含义是它可以被外部的代码访问Super
。在调用m()
时,我们可以调用privateMethod()
. 如果私有方法没有被继承,那么就会发生一些运行时异常,但事实并非如此。
Overriding
仅适用于类中的可见实例方法Sub
。如果一个方法是不可见的,Sub
并且在两个类中都定义了Super
,那么该对象具有两种能力,并且这两种方法都可以由可以访问特定方法的代码调用(参考下面的代码)
第 3 点的代码
public class Super{
private void privateMethod(){
System.out.println("private method defined in Super");
}
public void m(){
privateMethod();
}
}
public class Sub extends Super{
private void privateMethod(){
System.out.println("private method defined in Sub");
}
public void m2(){
privateMethod();
}
}
public class Other{
public static void main(String[] args){
Sub s = new Sub();
s.m(); // m() will invoke private method of Super
s.m2(); // m2() will invoke private method of Sub
}
}
说Sub
类不继承私有方法Super
意味着不能在对象上调用方法,Sub
因为行为不是继承的,因此不是(不属于)对象的一部分。上面我们看到情况并非如此。
解决方案
我认为关键的区别在于 Java 语言规范如何使用术语“继承”。(请注意,JLS 是权威文档,而不是 Java 教程。)
声明为私有的类的成员不会被该类的子类继承。
但是,在描述new
运算符的行为时,JLS 15.9.4,类实例创建表达式的运行时评估说(强调我的):
新对象包含在指定类类型及其所有超类中声明的所有字段的新实例。
这意味着超类的字段不被子类继承,但子类的实例对象仍然包含这些字段。同样的概念也适用于私有方法。
尽管可以在子类的实例上调用来自超类的私有方法,但该方法在形式上并不是该子类的一部分。私有方法仍然属于超类。
这是因为子类型(“is-a”)关系。子类型的实例是超类型的实例。该类不会将这些成员继承到自身中,但该类的实例仍然包含它们。
推荐阅读
- c++ - C++ 入门 5 版。: 在指针向量上使用排序是未定义的吗?
- reactjs - 在 AWS 上使用 NextJS SSR 部署 React 应用程序的最便宜方法?
- node.js - 如果找不到用户,mongoDB 查询会返回什么?
- python - 网页抓取时如何抓取 html 元素?
- ruby-on-rails - Rails 5.2.3 到 6.0.0 升级依赖地狱
- linux - rx_bytes 和 tx_bytes 如何在 /sys/class/net 中递增
- python - 最小和最大类型错误
- hangouts-chat - 如何为许多 GSuite 域获取 Hangouts Chat api 范围?
- reactjs - 打字稿中这种复杂的“不可分配给类型”错误的解释
- android - 添加 OkHttpClient 拦截器使请求进行多次