这是面试问题。
子类继承private吗 字段?
我的回答是“不”,因为我们不能使用“正常的面向对象的方式”访问它们。但是采访者认为它们是继承的,因为我们可以间接或使用反射访问这些字段,并且它们仍然存在于对象中。
回来后,我在javadoc中找到了以下引用:
超类中的私人成员 一个 子类不继承私有 父类的成员。
你知道面试官观点的论据吗?
这是面试问题。
子类继承private吗 字段?
我的回答是“不”,因为我们不能使用“正常的面向对象的方式”访问它们。但是采访者认为它们是继承的,因为我们可以间接或使用反射访问这些字段,并且它们仍然存在于对象中。
回来后,我在javadoc中找到了以下引用:
超类中的私人成员 一个 子类不继承私有 父类的成员。
你知道面试官观点的论据吗?
当前回答
私有类成员或构造函数只能在顶层类的主体(§7.6)中访问,该主体包含了成员或构造函数的声明。它不是由子类继承的。https://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.6
其他回答
子类不继承父类的私有成员。但是,如果父类具有用于访问其私有字段的公共或受保护方法,则子类也可以使用这些方法。
不。他们没有继承。
其他一些类可能间接使用它的事实不是关于继承,而是关于封装。
例如:
class Some {
private int count;
public void increment() {
count++;
}
public String toString() {
return Integer.toString( count );
}
}
class UseIt {
void useIt() {
Some s = new Some();
s.increment();
s.increment();
s.increment();
int v = Integer.parseInt( s.toString() );
// hey, can you say you inherit it?
}
}
您还可以通过反射在UseIt中获取count的值。这并不意味着你继承了它。
更新
即使值在那里,它也不会被子类继承。
例如,一个子类定义为:
class SomeOther extends Some {
private int count = 1000;
@Override
public void increment() {
super.increment();
count *= 10000;
}
}
class UseIt {
public static void main( String ... args ) {
s = new SomeOther();
s.increment();
s.increment();
s.increment();
v = Integer.parseInt( s.toString() );
// what is the value of v?
}
}
这和第一个例子的情况完全一样。属性计数是隐藏的,根本不被子类继承。不过,正如DigitalRoss指出的那样,价值是存在的,但不是通过继承来实现的。
这么说吧。如果你父亲很富有,给你一张信用卡,你仍然可以用他的钱买东西,但这并不意味着你继承了所有的钱,不是吗?
其他更新
但是,了解属性为什么在那里是非常有趣的。
坦白地说,我没有确切的术语来描述它,但正是JVM及其工作方式加载了“非继承”的父定义。
我们可以改变父类,子类仍然可以工作。
例如:
//A.java
class A {
private int i;
public String toString() { return ""+ i; }
}
// B.java
class B extends A {}
// Main.java
class Main {
public static void main( String [] args ) {
System.out.println( new B().toString() );
}
}
// Compile all the files
javac A.java B.java Main.java
// Run Main
java Main
// Outout is 0 as expected as B is using the A 'toString' definition
0
// Change A.java
class A {
public String toString() {
return "Nothing here";
}
}
// Recompile ONLY A.java
javac A.java
java Main
// B wasn't modified and yet it shows a different behaviour, this is not due to
// inheritance but the way Java loads the class
Output: Nothing here
我想确切的术语可以在这里找到:java虚拟机规范
正如其他人所指出的那样:
https://docs.oracle.com/javase/specs/jls/se8/html/jls - 8. - html # jls - 8.2:
声明为private的类的成员不会被继承 该类的子类。只声明类的成员 Protected或public由包中声明的子类继承 除了声明类的那个。
答案无疑是否定的,没有任何“如果”和“但是”。这围绕着继承的定义。根据定义,继承是针对类的,不是针对对象的。对象是使用类定义创建的。继承只是添加到类定义中的另一个块。那么,类是否继承了父类的私有成员?没有
Yes
重要的是要认识到,虽然有两个类,但只有一个对象。
当然,它继承了私有字段。它们大概是正确的对象功能所必需的,虽然父类的对象不是派生类的对象,但派生类的实例基本上肯定是父类的实例。如果没有所有的领域,就不可能是这样。
不,你不能直接访问它们。是的,它们是遗传的。他们必须如此。
这是个好问题!
更新:
呃,“不”
我想我们都学到了一些东西。由于JLS提出了确切的“不继承”措辞,所以回答“不继承”是正确的。由于子类不能访问或修改私有字段,因此,换句话说,它们不会被继承。但实际上只有一个对象,它确实包含私有字段,因此如果有人以错误的方式使用JLS和教程措辞,将很难理解OOP、Java对象以及实际发生的事情。
更新更新:
这里的争议涉及到一个根本的模糊:讨论的究竟是什么?的对象?或者我们在某种意义上谈论的是类本身?当描述类而不是对象时,允许有很大的自由度。因此,子类不继承私有字段,但作为子类实例的对象当然包含私有字段。
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.
将下面的文件保存为ParentClass.java并自己尝试它->
public class ParentClass {
private int x;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
class SubClass extends ParentClass {
private int y;
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void setXofParent(int x) {
setX(x);
}
}
class Main {
public static void main(String[] args) {
SubClass s = new SubClass();
s.setX(10);
s.setY(12);
System.out.println("X is :"+s.getX());
System.out.println("Y is :"+s.getY());
s.setXofParent(13);
System.out.println("Now X is :"+s.getX());
}
}
Output:
X is :10
Y is :12
Now X is :13
如果我们尝试在子类的方法中使用ParentClass的私有变量x,那么它不能被任何修改直接访问(意味着不能继承)。但是x可以通过原始类的setX()方法在子类中修改,就像在setXofParent()方法中做的那样,或者可以使用ChildClass对象使用setX()方法或setXofParent()方法修改,最终调用setX()。这里setX()和getX()是一种通往ParentClass的私有成员x的门。
另一个简单的例子是Clock超类将hours和min作为私有成员,将适当的getter和setter方法作为公共方法。然后是数字时钟作为时钟的子类。在这里,如果DigitalClock的对象不包含hours和mins成员,那么事情就搞砸了。