这是面试问题。
子类继承private吗 字段?
我的回答是“不”,因为我们不能使用“正常的面向对象的方式”访问它们。但是采访者认为它们是继承的,因为我们可以间接或使用反射访问这些字段,并且它们仍然存在于对象中。
回来后,我在javadoc中找到了以下引用:
超类中的私人成员 一个 子类不继承私有 父类的成员。
你知道面试官观点的论据吗?
这是面试问题。
子类继承private吗 字段?
我的回答是“不”,因为我们不能使用“正常的面向对象的方式”访问它们。但是采访者认为它们是继承的,因为我们可以间接或使用反射访问这些字段,并且它们仍然存在于对象中。
回来后,我在javadoc中找到了以下引用:
超类中的私人成员 一个 子类不继承私有 父类的成员。
你知道面试官观点的论据吗?
当前回答
不。私有字段没有被继承…所以我们才发明了"保护"这是有意为之。我想这证明了受保护修饰符的存在。
现在来看看上下文。继承是什么意思——如果它存在于从派生类创建的对象中?是的,它是。
如果你的意思是它是否对派生类有用。嗯,没有。
现在,当你进行函数式编程时,父类的私有字段不会以一种有意义的方式继承给子类。对于子类,超类的私有字段与任何其他类的私有字段相同。
在功能上,它不是遗传的。但理想情况是这样的。
好吧,刚刚看了一下Java教程,他们引用了这样的话:
超类中的私人成员 子类不继承父类的私有成员。但是,如果父类具有用于访问其私有字段的公共或受保护方法,则子类也可以使用这些方法。
参见:http://download.oracle.com/javase/tutorial/java/IandI/subclasses.html
我同意,这个领域是存在的。但是,子类在私有字段上没有任何特权。对于子类,私有字段与任何其他类的私有字段相同。
我相信这只是个人观点的问题。你可以左右争论的任何一方。这两种方法都是合理的。
其他回答
这取决于你对“继承”的定义。子类在内存中仍然有字段吗?肯定。它能直接访问它们吗?不。这只是定义的微妙之处;关键是要理解到底发生了什么。
不。他们没有继承。
其他一些类可能间接使用它的事实不是关于继承,而是关于封装。
例如:
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虚拟机规范
填充位/对齐和VTABLE中对象类的包含不被考虑。因此,子类的对象确实为超类的私有成员留有一席之地。但是,它不能从子类的对象中访问…
子类不继承父类的私有成员。但是,如果父类具有用于访问其私有字段的公共或受保护方法,则子类也可以使用这些方法
参考: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html: ~:文本=私人% 20成员在% 20 % % 20 20超类,由% % 20使用% 20 20 % 20子类。
私有成员(状态和行为)是继承的。它们(可以)影响类实例化的对象的行为和大小。更不用说,通过所有可用的封装破坏机制,或者它们的实现者可以假定,子类可以很好地看到它们。
虽然继承有一个“事实上的”定义,但它肯定与“可见性”方面没有联系,这是“不”答案所假设的。
所以,没有必要采取外交手段。JLS在这一点上是错误的。
任何认为他们不是“遗传”的假设都是不安全的和危险的。
因此,在两个事实上(部分)相互冲突的定义(我不会重复)中,唯一应该遵循的是更安全(或安全)的定义。