这是一个有趣的代码片段:
public class Superclass {
public static void main (String[] args){
Superclass obj = new Subclass();
obj.doSomething(); #prints"from Superclass"
}
private void doSomething(){System.out.println("from Superclass");}
}
class Subclass extends Superclass {
private void doSomething(){System.out.println("from Subclass");}
}
我知道子类不会继承其父级的私有成员,但是obj设法调用它应该没有访问权限的方法。 在编译时,obj的类型为Superclass,在运行时类型为Subclass。
这可能与doSomething()的调用发生在驱动程序类中的事实有关,这恰好是它自己的类(以及为什么可以首先调用doSomething())。
所以问题归结为,obj如何访问其父级的私有成员?
有趣的是看看子方法公开时会发生什么。 我已经做到了,它说:"来自Superclass"有趣的是,它没有超越它
私有方法仅适用于所有者。
甚至不是所有者的孩子,亲戚或朋友。
你自己回答了。由于私有方法不是继承的,因此超类引用会调用自己的私有方法。
如果通过"reference"表示存储在变量obj中的指针引用的Subclass实例,则它是一个循环答案。 该实例仍然是Subclass类型,它不应该访问父项私有成员。
关键是你将它分配给超类引用。 并且该方法是私有的,它不会被子类实现覆盖。 该引用只知道一个doSomething方法,它位于超类中。
Superclass obj = new Subclass();
此时,obj是事物,Subclass和Superclass对象。在变量声明中使用Superclass这一事实只是一个问题。
执行:obj.doSomething()时,您告诉编译器调用obj的私有方法doSomething()。因为您是从Superclass内的主静态方法执行的,所以编译器可以调用它。
如果您使用Subclass的main方法而不是Superclass中的方法,则无法访问该方法,因为正如您所说,它既不是继承的,也不是Subclass定义的一部分。
所以基本上你正确理解了继承。问题与私有方法的可见性有关。
它的工作原理是因为您从Superclass的方法中转换为Superclass。在该上下文中,编译器可以使用Superclass.doSomething。
如果要将超级和子类更改为两个不同的任意类A和B,与包含main方法的类无关,并尝试相同的代码,编译器会抱怨无法访问该方法。
由于对象obj的引用类型是Superclass,因此对doSomething()的调用尝试访问Superclass本身中定义的私有方法(不能覆盖私有方法)。
由于doSomething()可在Superclass内访问,main方法可以调用doSomething()而不会给出任何错误。
希望这可以帮助! :-)
当你使用这一行时:
Superclass obj = new Subclass();
您将Subclass转换为超类对象,该对象仅使用超类的方法和相同的数据。如果将它转换回子类,则可以再次使用Subclass方法,如下所示:
((Subclass)obj).doSomething(); #prints"from Subclass"
给定OP代码,((Subclass)obj).doSomething(); #prints"from Subclass"不会编译,因为您正在访问其类Subclass之外的私有方法。
why it's possible to invoke doSomething() in the first place?
为什么不? obj是Subclass和Superclass的实例,并且doSomething()在Superclass中声明并且obj中使用了doSomething(),因此您可以访问Superclass.doSomething(),您可以尝试重命名您的方法(例如:doAnotherThing()),您仍然可以访问它。
how does obj have access to a private member of its parent?
私有方法没有父/子,并且obj也是Superclass的类型,因此它可以访问在其中声明的所有私有方法/字段,因为在此类中使用了obj。如果您不在Superclass之外或者具有Superclass作为成员的类(嵌套类),您将失去此访问权限。
所以呢?
Superclass的私有方法和Subclass的私有方法之间没有关系/继承,即使它们具有相同的名称和签名,来自Java语言规范,Java SE 8版:
A private method and all methods declared immediately within a final
class (§8.1.1.2) behave as if they are final, since it is impossible
to override them.
要理解这个问题,您可以将私有方法与超类和子类的成员变量相关联。
所以我们知道成员变量不会在子类中被覆盖。
例如:
Class A{
int i = 10;
}
Class B extends A{
int i = 11;
}
Class C extends A {
int i = 12;
}
A a1 = new B();
print(a1.i) // Will print 10
A a2 = new B();
print(a2.i) // Will print 10
类似的方式,当没有继承引用变量时,将考虑超类。
您想通过显示最后两行代码来说明什么? 它们与前面的直线相同吗?
是的,他们是相同的..我只给了两个子类而不是一个..我认为一个应该没问题。
当我们在派生类中定义具有相同名称的私有方法时,它将成为一个新方法,因为派生类不会继承私有成员。
由于私有方法在类外部甚至不可见,我们永远不能从派生类调用基类私有方法,它会抛出一个编译错误:
线程"main"中的异常java.lang.Error:未解决的编译问题:
类型为Base的方法aPrivateMethod()不可见
我们可以使用向下转换到父类引用来调用派生类私有方法,该方法只能在该派生类中访问。