17

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

谁可以给我解释一下这个。我现在完全糊涂了。

4

5 回答 5

29

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

Java Documentation,

超类中的私有成员

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

JLS,

声明为私有的类的成员不会被该类的子类继承。只有声明为protected 或public 的类的成员才能被声明在一个包中的子类继承,而不是声明该类的那个。

一个有用的链接:子类是否继承私有字段?

于 2011-07-01T03:38:49.467 回答
29

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

假设您有两个类:Parentand Child,其中Childextends Parent。此外,Parent还有一个名为 的私有整数value

现在问题来了:Child继承私有value吗?在 Java 中,继承是这样定义的,答案是“否”。但是,在一般的 OOP 术语中,有一点含糊不清。

你可以说它不是继承的,因为没有地方可以Child显式引用value. 即任何代码this.value都不能在内部使用Child,也不obj.value能从某些调用代码中使用(显然)。

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

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

于 2011-07-01T03:50:57.613 回答
5

您将在这里 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

结论

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

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

于 2018-11-03T11:11:07.023 回答
3

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

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

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

很抱歉在这么旧的帖子中说明了什么,但这个问题总是有效的。

于 2012-04-27T18:11:33.703 回答
2

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

于 2018-07-28T00:15:29.573 回答