由于该对象(在标题中所述)可以调用子类覆盖的方法,它为什么不能调用子类的其他方法? 我需要回答尽可能详细,如内存组织,在JVM等内在逻辑
下面的代码会给你我的问题的清醒的认识。
class A
{
int x=10;
public A()
{
System.out.println("Constructor of class A called!!!");
}
public void sayGreetings()
{
System.out.println("accept hye from class A");
}
}
class C extends A
{
int x=30;//why this is not accessed by stated object.
public C()
{
System.out.println("Constructor of Class C caled!!!");
}
public void sayGreetings()
{
System.out.println("accept hye from class C");
}
public void ssa()
{
System.out.println("Sat Sri Akal ji from class C");
}
}
public class ParentClassTypeObject
{
public static void main(String[] args)
{
C cObj=new C();
cObj.sayGreetings();
cObj.ssa();
A aCObj=new C();//this is let say stated object,main object
aCObj.sayGreetings();/*here we invoked method will be child class's
overriden method.*/
//aCObj.ssa(); //why this line gives error
System.out.println("x="+aCObj.x);
}
}
Answer 1:
因为你要的对象的接口是你选择当你写了一句:
A aCObj = new C();
如果你想访问C
通过属性aCObj
变量声明为C
。
通过使其成为A
,你有可能在以后写:
aCObj = new A();
如此以来,该变量可以指向一个A
,或C
,编译器限制您访问由露出的接口定义的方法A
类型。
你仍然可以访问C
这些方法的定义 ,因为这是OOP(多态性)的要点之一。
Answer 2:
参考变量指向其是相同类型或子组相同类型的对象。
请考虑父母与子女两类凡父为超级类和子继承父类。 下面的图片会给你一个详细的解释。
在上面的图片,父类的参考变量将搜索儿童Object.It的父类对象会发现它,因为它是there.So会给output.And如果你有子类相同的方法(方法覆盖)它将执行子类overrided方法。
但对于儿童类引用变量,它不能在父类Object.So找出子类对象在这里,这是不可能的。
希望这个清除你的困惑。
Answer 3:
如果您编译代码,你会得到编译时错误(不运行时错误)。 这背后的原因是,
A aCObj=new C();
aCObj.sayGreetings(); / *编译器知道aCobj是类型A的基准而进行编译。 由于编译器认为aCobj是类型A和sayGreetings()方法是存在于类A,使没有错误而调用此方法* /的
aCObj.ssa();
/ *由于我是编译器上面提到的有没有关于运行时间的知识。 在运行时aCobj将指向型C类的对象,但在编译时,编译器只知道aCobj是类的类型,因为A类有没有这样的方法被称为SSA(),你会得到编译时错误。 * /
为对象的一个简单的规则:赋值运算符在编译时检查的左侧。 在运行时赋值运算符的右侧。 此声明:
Parent obj =new Child(); obj.method1(); obj.method2();
不管方法ü要使用父类型的OBJ引用调用,这些方法应该给出父类,因为在编译时,编译器将严格为您在父类的这些方法存在,即使它可能出现在子类。
Answer 4:
编译器决定是否可以调用基于参考variable.So的类型的方法,如果参考变量是A级的,你只能叫A类的方法
而且编译器决定调用根据实际类型的对象,而不是引用变量的开始自下而上的继承树检查其类型的方法。(从子类一路上涨开始)
所以,当你说这种情况下aCObj.sayGreetings();
编译器首先检查aCObj的引用类型是A
。类A具有sayGreetings()
方法,以便其ok.But实际对象是C
。所以编译器从子类(C)开始发现这个方法是否被实施的所有对超类(A)。该方法的方式`sayGreetings()
中C类被覆盖。 所以它调用C class sayGreetings() method
(子类)。
在另一方面的ssa()
方法是类C的和由于参考变量是类A的当尝试编译器提供了一个错误aCObj.ssa();
它只是polymorphism.Since一个A类参考变量可以是A或C对象编译器限制只访问所共有的方法,其是超类的方法A.Next它检查该方法是否是在类的实现实际物体(C)。如果它是不是向上移动到超类(A)和如果实现了它调用子类的方法(C)调用superclass.But的方法
Answer 5:
对象是A型不是C的,所以如果你把它公开,你可以,你不能访问实例变量,我认为。
Answer 6:
由于aCObj
被声明为类型A
所以只能在A类声明的方法都可以访问。 编译器不能保证它是C型也
如
您还可能有
public class B extends A {
public void sayGreetings() {
...
}
}
这并不一定SSA的方法,但仍然被分配给声明为A类对象
Answer 7:
壳体1父类的参考变量可以指向它的子类的一个对象..情况下2.指向它的子类的对象的父类的参考变量可以被类型强制转换到其子的一个目的类。
在情况1中:父类的参考变量只能调用在父类中定义的方法,并且还可以调用子类的被重写父class.But的方法不能调用专门仅是方法的方法在子类。
在情况2:引用父类的变量可以调用它的子类的方法也。
这是由于多态性的原则。
Answer 8:
这里是你的既定查询详细的解释:
答案是“多态”和“静态类型”的交叉点 。 因为Java是在编译时静态类型你从编译器的某些保证,但你不得不遵守规则,以换取或代码将无法编译。 在此,相关担保是一种亚型(如儿童)的每个实例都可以作为它的超类型(如父母)的一个实例。 例如,可以保证的是,当你访问employee.getEmployeeDetails或employee.name方法或字段可能被分配给父类型的可变雇员任何非空物体上定义。 为了使这一保证,编译器只考虑静态类型(基本的变量引用的类型,母体)决定时,你可以访问什么。 所以你不能访问在运行时类型的对象,儿童的定义的任何成员。
答案已采取从以下链接: 为什么我们给家长参考Java中的子对象?
文章来源: Why parent class type reference variable having reference to child class object can't access child class's Methods