子类会继承私有字段吗?
这是一道面试题。
子类是否继承私有字段?
我回答“否”,因为我们无法使用“正常的 OOP 方式”访问它们。但面试官认为它们是继承的,因为我们可以间接或使用反射访问这些字段,并且它们仍然存在于对象中。
回来后,我在 javadoc:
超类中的私人成员
子类不会继承父类的私有成员。
你知道面试官的观点有什么论据吗?
This is an interview question.
Do subclasses inherit private fields?
I answered "No", because we can't access them using the "normal OOP way". But the interviewer thinks that they are inherited, because we can access such fields indirectly or using reflection and they still exist in the object.
After I came back, I found the following quote in the javadoc:
Private Members in a Superclass
A subclass does not inherit the private members of its parent class.
Do you know any arguments for the interviewer's opinion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(21)
这里的问题/答案中的大部分混乱都围绕着继承的定义。
显然,正如DigitalRoss解释的,一个OBJECT 子类必须包含其超类的私有字段。正如他所说,无法访问私人成员并不意味着它不存在。
但是,这与类的继承概念不同。就像 Java 世界中的情况一样,存在语义问题,仲裁者是 Java 语言规范(当前为第三版)。
正如 JLS 所说(https:/ /docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):
这解决了面试官提出的确切问题:“子类是否继承私有字段”。 (强调是我添加的)
答案是否定的。他们没有。子类的对象包含其超类的私有字段。子类本身没有其超类的私有字段的概念。
这是迂腐的语义吗?是的。这是一个有用的面试问题吗?可能不会。但 JLS 为 Java 世界建立了定义,并且(在本例中)明确地做到了这一点。
Most of the confusion in the question/answers here surrounds the definition of Inheritance.
Obviously, as DigitalRoss explains, an OBJECT of a subclass must contain its superclass's private fields. As he states, having no access to a private member doesn't mean its not there.
However, this is different than the notion of inheritance for a class. As is the case in the Java world, where there is a question of semantics the arbiter is the Java Language Specification (currently 3rd edition).
As the JLS states (https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2):
This addresses the exact question posed by the interviewer: "do subCLASSES inherit private fields". (emphasis added by me)
The answer is No. They do not. OBJECTS of subclasses contain private fields of their superclasses. The subclass itself has NO NOTION of private fields of its superclass.
Is it semantics of a pedantic nature? Yes. Is it a useful interview question? Probably not. But the JLS establishes the definition for the Java world, and it does so (in this case) unambiguously.
是的
重要的是要认识到,虽然有两个类,但只有一个对象。
所以,是的,它当然继承了私有字段。据推测,它们对于正确的对象功能至关重要,虽然父类的对象不是派生类的对象,但派生类的实例大多肯定是父类的实例。如果没有所有字段,情况就不可能如此。
不,您无法直接访问它们。是的,它们是遗传的。他们必须是这样。
这是个好问题!
更新:
呃,“不”
好吧,我想我们都学到了一些东西。由于 JLS 起源了确切的“非继承”措辞,回答“否”是正确的。由于子类无法访问或修改私有字段,那么,换句话说,它们不是继承的。但实际上只是只有一个对象,它确实确实包含私有字段,因此如果有人以错误的方式理解JLS和教程措辞,理解 OOP、Java 对象以及真正发生的事情将是相当困难的。
更新更新:
这里的争议涉及一个根本性的歧义:到底正在讨论什么?对象?或者我们在某种意义上谈论的是类本身吗?在描述类而不是对象时,允许有很大的自由度。因此子类不会继承私有字段,但作为子类实例的对象肯定包含私有字段。
Yes
It's important to realize that while there are two classes, there is only one object.
So, yes, of course it inherited the private fields. They are, presumably, essential for proper object functionality, and while an object of the parent class is not an object of the derived class, an instance of the derived class is mostly definitely an instance of the parent class. It could't very well be that without all of the fields.
No, you can't directly access them. Yes, they are inherited. They have to be.
It's a good question!
Update:
Err, "No"
Well, I guess we all learned something. Since the JLS originated the exact "not inherited" wording, it is correct to answer "no". Since the subclass can't access or modify the private fields, then, in other words, they are not inherited. But there really is just one object, it really does contain the private fields, and so if someone takes the JLS and tutorial wording the wrong way, it will be quite difficult to understand OOP, Java objects, and what is really happening.
Update to update:
The controversy here involves a fundamental ambiguity: what exactly is being discussed? The object? Or are we talking in some sense about the class itself? A lot of latitude is allowed when describing the class as opposed to the object. So the subclass does not inherit private fields, but an object that is an instance of the subclass certainly does contain the private fields.
不。私有字段不会被继承……这就是发明 Protected 的原因。这是设计使然。我想这证明了 protected 修饰符的存在是合理的。
现在来看看上下文。继承是什么意思——如果它存在于从派生类创建的对象中?是的。
如果你的意思是它对派生类有用。嗯,不。
现在,当您进行函数式编程时,子类不会以有意义的方式继承超类的私有字段。对于子类,超类的私有字段与任何其他类的私有字段相同。
从功能上来说,它不是继承的。但理想,确实如此。
好吧,刚刚查看了 Java 教程,他们引用了以下内容:
参考:http://download.oracle.com/javase/tutorial/java /IandI/subclasses.html
我同意,该字段就在那里。但是,子类在该私有字段上没有任何特权。对于子类,私有字段与任何其他类的任何私有字段相同。
我认为这纯粹是观点问题。你可以塑造任何一方的论点。最好双向证明。
No. Private fields are not inherited... and that's why Protected was invented. It is by design. I guess this justified the existence of protected modifier.
Now coming to the contexts. What you mean by inherited -- if it is there in the object created from derived class? yes, it is.
If you mean can it be useful to derived class. Well, no.
Now, when you come to functional programming the private field of super class is not inherited in a meaningful way for the subclass. For the subclass, a private field of super class is same as a private field of any other class.
Functionally, it's not inherited. But ideally, it is.
OK, just looked into Java tutorial they quote this:
refer: http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html
I agree, that the field is there. But, subclass does not get any privilege on that private field. To a subclass, the private field is same as any private field of any other class.
I believe it's purely matter of point-of-view. You may mould the argument either side. It's better justify both way.
这取决于你对“继承”的定义。子类内存中还有字段吗?确实。可以直接访问它们吗?不,这只是定义的微妙之处;重点是要了解到底发生了什么。
It depends on your definition of "inherit". Does the subclass still have the fields in memory? Definitely. Can it access them directly? No. It's just subtleties of the definition; the point is to understand what's really happening.
我将用代码演示这个概念。子类实际上继承超类的私有变量。唯一的问题是它们无法访问
子对象,除非您为私有变量提供公共 getter 和 setter
在超级班里。
考虑 Dump 包中的两个类。孩子扩展了父母。
如果我没记错的话,内存中的子对象由两个区域组成。一个仅是父部分,另一个仅是子部分。孩子可以访问私人空间
仅通过父级中的公共方法在其父级代码中包含部分。
这样想吧。波拉特的父亲博尔托克有一个装有 10 万美元的保险箱。他不想安全地共享他的“私有”变量。因此,他没有提供保险箱钥匙。波拉特继承了保险箱。可是,如果连打开都打不开,那又有什么用呢?如果只有他的
爸爸已经提供了钥匙。
父级 -
子级 -
I will demonstrate the concept with code. Subclasses ACTUALLY inherit the private variables of super class. The only problem is that they are not accessible to the
child objects unless you provide public getters and setters for the private variables
in the super class.
Consider two class in package Dump. Child extends Parent.
If I remember correctly, a child object in memory consists of two regions. One is the parent part only and the other is the child part only. A child can access the private
section in the code of its parent only via a public method in the parent.
Think of it this way. Borat's father Boltok has a safe containing $100,000. He does not want to share his "private" variable safe. So, he does not provide a key for the safe. Borat inherits the safe. But, what good is it if he cannot even open it ? If only his
dad had provided the key.
Parent -
Child -
不,他们不会继承它。
其他类可能间接使用它这一事实并没有说明继承,而是说明了封装。
例如:
您还可以通过反射获取
UseIt
内部count
的值。这并不意味着,你继承了它。更新
即使该值存在,它也不会被子类继承。
例如子类定义为:
这与第一个示例的情况完全相同。属性
count
是隐藏的,并且子类根本不继承。尽管如此,正如 DigitalRoss 指出的那样,价值是存在的,但不是通过继承的方式实现的。这样说吧。如果你父亲很有钱,给了你一张信用卡,你仍然可以用他的钱买东西,但这并不意味着你继承了所有的钱,不是吗?
其他更新
这很有趣,知道为什么 坦率地说,
我没有确切的术语来描述它,但 JVM 及其工作方式也加载了“非继承”父定义。
我们实际上可以更改父类,而子类仍然可以工作。
例如:
我想可以在这里找到确切的术语:JavaTM 虚拟机规范
No. They don't inherit it.
The fact some other class may use it indirectly says nothing about inheritance, but about encapsulation.
For instance:
You can also get the value of
count
insideUseIt
via reflection. It doesn't means, you inherit it.UPDATE
Even though the value is there, it is not inherited by the subclass.
For instance a subclass defined as:
This is exactly the same situation as the first example. The attribute
count
is hidden and not inherited by the subclass at all. Still, as DigitalRoss points out, the value is there, but not by means on inheritance.Put it this way. If your father is wealthy and gives you a credit card, you can still buy thing with his money, but doesn't mean you have inherited all that money, does it?
Other update
It is very interesting though, to know why the attribute is there.
I frankly don't have the exact term to describe it, but it's the JVM and the way it works that loads also the "not inherited" parent definition.
We could actually change the parent and the subclass will still work.
For instance:
I guess the exact term could be found here: The JavaTM Virtual Machine Specification
好吧,我对面试官问题的回答是 - 私有成员不会在子类中继承,但只能通过公共 getter 或 setter 方法或原始类的任何此类适当方法来访问它们。通常的做法是保持成员私有并使用公共的 getter 和 setter 方法访问它们。那么,当对象无法使用 getter 和 setter 方法所处理的私有成员时,仅继承 getter 和 setter 方法有什么意义呢?这里的“继承”只是意味着它可以直接在子类中通过子类中新引入的方法来使用。
将以下文件保存为 ParentClass.java 并自行尝试 ->
如果我们尝试在子类的方法中使用ParentClass的私有变量x,那么它就不能直接访问以进行任何修改(意味着不能继承)。但是 x 可以通过原始类的 setX() 方法在子类中进行修改,就像在 setXofParent() 方法中所做的那样,或者可以使用 ChildClass 对象使用 setX() 方法或最终调用 setX() 的 setXofParent() 方法来修改 x。所以这里 setX() 和 getX() 是通往 ParentClass 的私有成员 x 的某种门。
另一个简单的例子是 Clock 超类将小时和分钟作为私有成员,并将适当的 getter 和 setter 方法作为公共成员。然后是 DigitalClock 作为 Clock 的子类。在这里,如果 DigitalClock 的对象不包含小时和分钟成员,那么事情就会搞砸。
Well, my answer to interviewer's question is - Private members are not inherited in sub-classes but they are accessible to subclass or subclass's object only via public getter or setter methods or any such appropriate methods of original class. The normal practice is to keep the members private and access them using getter and setter methods which are public. So whats the point in only inheriting getter and setter methods when the private member they deal with are not available to the object? Here 'inherited' simply means it is available directly in the sub-class to play around by newly introduced methods in sub-class.
Save the below file as ParentClass.java and try it yourself ->
If we try to use private variable x of ParentClass in SubClass's method then it is not directly accessible for any modifications (means not inherited). But x can be modified in SubClass via setX() method of original class as done in setXofParent() method OR it can be modified using ChildClass object using setX() method or setXofParent() method which ultimately calls setX(). So here setX() and getX() are kind of gates to the private member x of a ParentClass.
Another simple example is Clock superclass has hours and mins as private members and appropriate getter and setter methods as public. Then comes DigitalClock as a sub-class of Clock. Here if the DigitalClock's object doesn't contain hours and mins members then things are screwed up.
好吧,这是一个非常有趣的问题,我研究了很多并得出结论:超类的私有成员确实在子类的对象中可用(但不可访问)。为了证明这一点,这里是一个包含父类和子类的示例代码,我将子类对象写入txt文件并读取文件中名为“bhavesh”的私有成员,从而证明它确实在子类中可用类,但由于访问修饰符而无法访问。
打开 MyData1.txt 并搜索名为“bhavesh”的私有成员。请告诉我你们的想法。
Ok, this is a very interesting problem I researched a lot and came to a conclusion that private members of a superclass are indeed available (but not accessible) in the subclass's objects. To prove this, here is a sample code with a parent class and a child class and I am writing child class object to a txt file and reading a private member named 'bhavesh' in the file, hence proving it is indeed available in the child class but not accessible due to the access modifier.
Open MyData1.txt and search for the private member named 'bhavesh'. Please let me know what you guys think.
看起来子类确实继承了私有字段,因为这些字段在子类的内部工作中使用(从哲学上讲)。子类在其构造函数中调用超类构造函数。如果超类构造函数在其构造函数中初始化了这些字段,则超类私有字段显然会被调用超类构造函数的子类继承。这只是一个例子。但是,如果没有访问器方法,子类当然无法访问超类私有字段(这就像无法弹出 iPhone 的后面板以取出电池来重置手机......但电池仍然在那里)。
聚苯乙烯
我遇到过的继承的众多定义之一:
“继承——一种编程技术,允许派生类扩展基类的功能,继承其所有状态(重点是我的)和行为。”
私有字段即使不能被子类访问,也是超类的继承状态。
It would seem that a subclass does inherit the private fields in that these very fields are utilized in the inner workings of the subclass (philosophically speaking). A subclass, in its constructor, calls the superclass constructor. The superclass private fields are obviously inherited by the subclass calling the superclass constructor if the superclass constructor has initialized these fields in its constructor. That's just an example. But of course without accessor methods the subclass cannot access the superclass private fields (it's like not being able to pop the back panel of an iPhone to take the battery out to reset the phone... but the battery is still there).
PS
One of the many definitions of inheritance that I have come across:
"Inheritance -- a programming technique that allows a derived class to extend the functionality of a base class, inheriting all of its STATE (emphasis is mine) and behaviour."
The private fields, even if not accessible by the subclass, are the inherited state of the superclass.
例如,
For example,
不考虑填充位/对齐以及在 VTABLE 中包含对象类。所以子类的对象确实有一个地方可以容纳超类的私有成员。但是,无法从子类的对象访问它......
Padding bits/Alignment and the inclusion of Object Class in the VTABLE is not considered. So the object of the subclass does have a place for the private members of the Super class. However, it cannot be accessed from the subclass's objects...
我不得不回答 Java 中的私有字段是继承的。让我演示一下:
如果您在程序中运行
Bar bar = new Bar();
,那么您将始终在输出框中看到数字“2”。因为整数“x”是用update()
和getX()
方法封装的,所以可以证明该整数是继承的。令人困惑的是,因为您无法直接访问整数“x”,所以人们认为它不是继承的。然而,类中的每个非静态事物,无论是字段还是方法,都是继承的。
I would have to answer that private fields in Java are inherited. Allow me to demonstrate:
If you run in a program
Bar bar = new Bar();
, then you will always see the number "2" in the output box. Because the integer "x" is encapsulated with the methodsupdate()
andgetX()
, then it can be proven that the integer is inherited.The confusion is that because you can't directly access the integer "x", then people argue that it isn't inherited. However, every non-static thing in a class, be it field or method, is inherited.
不,私有字段不会被继承。唯一的原因是子类无法直接访问它们。
No, private fields are not inherited. The only reason is that subclass can not access them directly.
正如其他人指出的 JLS 摘录:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2:
毫无疑问,答案是否,没有任何不确定性。这围绕着继承的定义。根据定义,继承是针对类的,而不是针对对象的。对象是使用类定义创建的。继承只是添加到类定义中的另一个块。 那么,一个类是否继承了超类的任何私有成员?否
As others have pointed out exerpt from JLS:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2:
The answer is NO without a doubt, without any iffs and buts. That revolves around the definition of inheritance. By definition inheritance is for classes, not for objects. Objects are created using class definitions. Inheritance is just another block to add to definition of a
class
. So, does a class inherits any private member of super class? NO我相信,答案完全取决于所提出的问题。我的意思是,如果问题是
如果我们查看访问说明符详细信息<,那么答案是否 /a>,有人提到,私有成员只能在类本身内部访问。
但是,如果问题是
这意味着,您将如何访问私有成员并不重要。在这种情况下,我们可以在超类中创建公共方法,并且您可以访问私有成员。因此,在这种情况下,您将创建一个接口/桥来访问私有成员。
其他OOPs语言如C++,都有
友元函数
的概念,通过它我们可以访问其他类的私有成员。I believe, answer is totally dependent on the question, which has been asked. I mean, if question is
Then answer is No, if we go through the access specifier details, it is mentioned, private members are accessible only within the class itself.
But, if question is
Which means, it doesn't matters, what you will do to access the private member. In that case, we can make public method in the super-class and you can access the private member. So, in this case you are creating one interface/bridge to access the private member.
Other OOPs language like C++, have the
friend function
concept, by which we can access the private member of other class.我们可以简单地说,当超类被继承时,超类的私有成员实际上成为子类的私有成员,并且不能被进一步继承,也不能被子类的对象访问。
We can simply state that when a superclass is inherited, then the private members of superclass actually become private members of the subclass and cannot be further inherited or are inacessible to the objects of subclass.
私有类成员或构造函数只能在顶级类的主体内访问(§7.6) 包含成员或构造函数的声明。它不被子类继承。 https://docs.oracle.com /javase/specs/jls/se7/html/jls-6.html#jls-6.6
A private class member or constructor is accessible only within the body of the top level class (§7.6) that encloses the declaration of the member or constructor. It is not inherited by subclasses. https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6
子类不会继承其父类的私有成员。但是,如果超类具有用于访问其私有字段的公共或受保护方法,则子类引用也可以使用这些方法
:
https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html#:~:text=Private%20Members%20in%20a%20Superclass,be%20used %20by%20the%20子类。
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass
reference:
https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html#:~:text=Private%20Members%20in%20a%20Superclass,be%20used%20by%20the%20subclass.
我可以尽力帮助你。
当子类(例如,名为 B)扩展超类(例如,名为 A)时,它会自动从其超类继承字段(例如属性和/或方法)。
现在,B 在其内存布局中为 A 类中的每个字段(甚至是私有字段)提供了空间。事实上,Java 不允许子类 B 使用私有字段,因为它们是私有的。
I can try to help you.
When a subclass(named B, for example) extends a superclass (named A, for example), it automatically inherits fields (such as attributes and/or methods) from its superclass.
Now, B in its Memory Layout has the space for every field in class A even the private ones. The fact is that Java doesn't allow the subclass B to use the private fields because they are private.
子类不会继承父类的私有成员。但是,如果超类具有用于访问其私有字段的公共或受保护方法,则子类也可以使用这些方法。
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.
私有成员(状态和行为)是继承的。它们(可以)影响类实例化的对象的行为和大小。更不用说通过所有可用的或可由其实现者假设的封装破坏机制,它们对于子类来说是非常明显的。
尽管继承有一个“事实上的”定义,但它绝对与“可见性”方面没有联系,而“可见性”方面是由“否”答案假设的。
因此,没有必要采取外交手段。 JLS 在这一点上是错误的。
任何认为它们不是“继承”的假设都是不安全和危险的。
因此,在两个事实上(部分)冲突的定义(我不会重复)中,唯一应该遵循的定义是更安全的定义。
Private members (state and behavior) are inherited. They (can) affect the behavior and size of the object which is instantiated by the class. Not to mention that they are very well visible to the subclasses via all the encaptulation-breaking mechanisms that are available, or can be assumed by their implementers.
Although inheritance has a "defacto" definition, it definitely has no link to "visibility" aspects, which get assumed by the "no" answers.
So, there is no need to be diplomatic. JLS is just wrong at this point.
Any assumption that they are not "inherited" is unsafe and dangerous.
So among two defacto (partially) conflicting definitions (which I will not repeat), the only one that should be followed is the one that is safer (or safe).