class A{
public void a1(){....};
public void a2(){....};
}class B extends A{
public void a1(){....};
public void b1(){....};
}public class C{
public static void main(String[] args){
A one = new B();
one.a1();
one.a2();
one.b1();//error
}
}在上面的例子中,当一个父类变量引用子类对象时,该变量可以调用父类中定义的两个方法,却不可以访问子类特有的方法,这说明该变量只是能够访问子类实例的父类部分,但是a1()方法也被子类覆盖了,应该属于子类部分啊,该变量却可以访问a1(),而不能访问b1().
这是为什么???????
在堆中是如何划分子类和父类各自的部分呢?如果说子类中的a1()覆盖了父类中a1()后,成为基类部分,那么又为什么在子类a1()的实现中可以访问子类的域呢?说明不可能是基类部分.那这中间究竟是什么原因呢?请哪位高手帮小第看看,小第刚学java,有很多地方需请教各位高手!!!!!!!
public void a1(){....};
public void a2(){....};
}class B extends A{
public void a1(){....};
public void b1(){....};
}public class C{
public static void main(String[] args){
A one = new B();
one.a1();
one.a2();
one.b1();//error
}
}在上面的例子中,当一个父类变量引用子类对象时,该变量可以调用父类中定义的两个方法,却不可以访问子类特有的方法,这说明该变量只是能够访问子类实例的父类部分,但是a1()方法也被子类覆盖了,应该属于子类部分啊,该变量却可以访问a1(),而不能访问b1().
这是为什么???????
在堆中是如何划分子类和父类各自的部分呢?如果说子类中的a1()覆盖了父类中a1()后,成为基类部分,那么又为什么在子类a1()的实现中可以访问子类的域呢?说明不可能是基类部分.那这中间究竟是什么原因呢?请哪位高手帮小第看看,小第刚学java,有很多地方需请教各位高手!!!!!!!
从父类中继承的方法经转型后,就是子类的方法,自然可以访问子类的域.
Thinking in Java讲的蛮详细的,你可以看一下!
java 实例源文件
class A
{
public void fun1()
{System.out.prinln("**");}
public void fun2()
{System.out.println("*****");}
}
class B extends A
{
public void fun2()
{System.out.println("the B.fun2 is calling:"+"*****");}
public void fun3()
{System.out.println("#####");}}
public class Test
{
public static void main(String arg[])
{
A one=new A();
A two=new B();//在堆内存中生成B实例对象,在栈内存中定义了一个A类引用变量指向B实例对象
one.fun1();
one.fun2();
two.fun1();
two.fun2();
//two.fun3();
}
}
输出:
**
****
**
the B.fun2 is calling:*****
由结果可以看到,虽然堆内存中同样存在一个A类对象但是因为定义的A类引用变量指向的是内存中的B对象,在调用two.fun2();方法。指针two是到B对象内存中去调用。为什么不能调用fun3呢?
因为定义two为A类引用变量本身就相当于标明two是父类类型的因此它的引用也要以父类为模版,超出的部分会被剔除。
A one = new B();
one.a1();
one.a2();
one.b1();//error
用父类引用子类对象其实是这样的:可能(C++是这样的也许JAVA也是这样反正原理是一样的)
class A{
Hashtable vtable;(类似Hashtable的数据结构)
public void a1(){....};
public void a2(){....};
}
当对象访问成员函数是,是这样的:
假如要访问a1() JRE会根据a1()在类模板中的顺序来访问VTABLE
a1()-------->vtable[a1函数的地址]----->真正的a1函数
当发生覆盖调用时JRE会动态修改VTABLE中函数的地址,使之指向真正的函数。
就像one.a1();指向子类的函数地址,因为子类中没有b1()函数,所以VTABLE中的地址为NULL所以会出错