Java继承中的私有成员

Posted

技术标签:

【中文标题】Java继承中的私有成员【英文标题】:Private members in Java inheritance 【发布时间】:2011-09-26 11:09:41 【问题描述】:

有人告诉我,Java 子类可以继承其超类的所有成员。那么这是否意味着即使是私人成员?我知道它可以继承受保护的成员。

谁能给我解释一下。我现在完全糊涂了。

【问题讨论】:

【参考方案1】:

您将在这里 100% 满意。我在我的电脑上测试了它,我得出的结论是我要把它贴在这里。只需通过下面编写的程序,查看程序输出并阅读最后给出的结论。 要自己测试,请将整个程序复制并保存在名为“InheritanceTest.java”的文件中,然后编译并最终运行。

程序

// Testing if a subclass can access the private members of a superclass

class Class1 
    private String name;

    public void setName(String name) 
        this.name = name;
        System.out.println("The name has been set successfully.");
    

    public void showName() 
        System.out.println("The name is: " + name);
    


class Class2 extends Class1 
    private int age;

    public void setAge(int age) 
        this.age = age;
        System.out.println("The age has been set successfully.");
    

    public void showAge() 
        System.out.println("The age is: " + age);
    

    public void displayName() 
        //Accessing the private member of superclass here
        //System.out.println("The name is: " + name); //error, can't compile because access to the private member name of the superclass Class1 is not permitted here.
    


class InheritanceTest 
    public static void main(String[] args) 

        Class1 c1 = new Class1();
        Class2 c2 = new Class2();

        c1.setName("Name_C1");
        c2.setName("Name_C2"); //No error, setName() is a public member of the superclass which indirectly gives access to the private member "name".

        c1.showName();
        c2.showName(); //No error, showName() is a public member of the superclass which indirectly gives access to the private member "name".

        c2.setAge(25);
        c2.showAge();

        //c2.displayName(); //error
    

输出

The name has been set successfully.
The name has been set successfully.
The name is: Name_C1
The name is: Name_C2
The age has been set successfully.
The age is: 25

结论

是的,子类可以间接访问超类的私有成员。子类不能直接访问超类的私有成员。

超类的所有公共、私有和受保护成员(即所有字段和方法)都由子类继承,但子类只能直接访问超类的公共和受保护成员。如果从超类继承的成员允许访问超类的私有成员,则子类可以使用这个继承的成员访问超类的私有成员。

【讨论】:

【参考方案2】:

这取决于您对继承一词的确切用法。我会举例说明。

假设您有两个类:ParentChild,其中 Child 扩展了 Parent。此外,Parent 有一个名为 value 的私有整数。

现在问题来了:Child 是否继承了私有的value?在 Java 中,定义继承的方式是回答“否”。但是,在一般的 OOP 术语中,有轻微的歧义。

您可以说它没有继承,因为Child 无法明确引用value。 IE。 this.value 之类的任何代码都不能在 Child 中使用,obj.value 也不能在某些调用代码中使用(显然)。

然而,在另一种意义上,你可以说value 继承的。如果您认为Child 的每个实例也是Parent 的一个实例,那么该对象必须包含value 中定义的Parent。即使Child 类对此一无所知,一个名为value 的私有成员仍然存在于Child 的每个实例中。所以从这个意义上说,你可以说value继承了Child

所以不要使用“继承”这个词,只要记住子类不知道父类中定义的私有成员。但也要记住,这些私有成员仍然存在于子类的实例中。

【讨论】:

【参考方案3】:

虽然https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2 表明私有成员没有被继承。实际上,它是由子类继承的。当我们使用调试器跟踪变量时,它会显示“继承”标签下的私有成员,所以请尝试一下。还有一个帖子在讨论这个问题,大部分人认为不是遗传的,这误导了很多人,包括我一开始。

【讨论】:

【参考方案4】:

IMO 绝不是定义问题。在基于类的继承中,意味着将行为传播给后代。因此,私有成员确实会被继承,我不会详细说明这是如何发生的。

实际上,我发现“不继承”的答案对新开发人员来说是危险的,他们并没有立即理解私有成员隐藏在你的类的皮肤下并且它们(可能)对其行为产生严重影响,对象的大小等。

在计算机科学中“开发先于理解”是很常见的,但是我们要避免构建(或破坏)我们对 OOP 的概念化,假设某些技术人员在编写一个著名的基于类的 OO 平台手册时采用了错误的“定义” .

很抱歉在这么旧的帖子中陈述了一些东西,但问题总是有效的。

【讨论】:

归结为“继承”的含义。链接到的文档@roadRunner 有两种方式:在开头附近它说“子类继承其超类的所有成员(字段、方法和嵌套类)。”然后自相矛盾说它不继承私有成员。就个人而言,我认为它们是被继承的,因为它们存在,它们只是不能直接访问。我很好奇“继承”对 Java 的含义是否有真正的定义,或者可能是一般的 OO。 @sharakan:今天我们只有一个事实上的定义。 因此,如果我们比较两种似乎作为事实定义出现的替代方案,一辆汽车会看到以下内容:假设一辆汽车声明私有成员不被继承,这对于新开发人员来说是完全误导和危险的。认为超类私有成员(状态和行为元素)消失了。因此,只有一个定义是可以安全假设的。因此,不存在“其他定义”的问题,这是我原始信息的基础(“无论定义如何”)。另一个定义不做任何假设;-)【参考方案5】:

不,私有成员不被继承,因为私有成员的范围仅限于定义它的类.只有 public 和 protected 成员被继承。

来自Java Documentation

超类中的私有成员

子类不继承 其父类的私有成员。 但是,如果超类有 public 或访问其受保护的方法 私有字段,这些也可以使用 由子类。嵌套类有 访问所有私有成员 它的封闭类——包括字段和 方法。因此,公众或 由 a 继承的受保护的嵌套类 子类可以间接访问所有 超类的私有成员。

来自JLS

类的成员被声明 私有不被继承 该类的子类。只有会员 被声明为受保护的类的 或 public 被子类继承 在包装以外的其他包装中声明 声明类的地方。

一个有用的链接:Does subclasses inherit private fields?

【讨论】:

澄清一下,子类的所有字段和方法仍然存在,但它们只能通过可以访问它们(或反射)的非私有方法间接访问 @PeterLawrey 对于渴望深入了解语言架构的每个人来说,这都是非常重要的一点。我的猜测是,超类型的所有成员(包括私有成员)都在堆中分配到一个非常相同的子类实例的地址/范围中(调试器将超类私有成员显示为子类的一部分。 .据我所知,在子类的实例化过程中,各个超类实例不是单独创建的..而是它们的成员包含在子类的实例中)..它们只是直接不可用。

以上是关于Java继承中的私有成员的主要内容,如果未能解决你的问题,请参考以下文章

06JAVA基础面向对象-继承/多态

06JAVA基础面向对象-继承/多态

java中私有的属性、静态成员可以被子类继承吗?

java学习--基础知识进阶第二天--笔记

继承的基本概念: Java不支持多继承,也就是说子类至多只能有一个父类。 子类继承了其父类中不是私有的成员变量和成员方法,作为自己的成员变量和方法。 子类中定义的成员变量和父类中

java中字段继承问题--子类不能继承父类的私有成员