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

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

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

【问题讨论】:

    标签: java inheritance subclass superclass private-members


    【解决方案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 对于渴望深入了解语言架构的每个人来说,这都是非常重要的一点。我的猜测是,超类型的所有成员(包括私有成员)都在堆中分配到一个非常相同的子类实例的地址/范围中(调试器将超类私有成员显示为子类的一部分。 .据我所知,在子类的实例化过程中,各个超类实例不是单独创建的..而是它们的成员包含在子类的实例中)..它们只是直接不可用。
          猜你喜欢
          • 2018-05-11
          • 2020-09-04
          • 2020-09-01
          • 2011-02-10
          • 2012-01-04
          • 2019-03-13
          • 2013-02-12
          • 2015-01-21
          相关资源
          最近更新 更多