父类引用指向子类对象(Java中的多态)

来源:互联网 发布:rufus制作linux启动盘 编辑:程序博客网 时间:2024/04/30 03:39
class Father { 
void print() { System.out.println("Father print"); } 



class Son extends Father { 
void print() { System.out.println("Son print"); }
void show() { System.out.println("Son show"); }
}


class Demo { 
public static void main(String args[]) { 
 Father obj = new Son();
 obj.print(); // 调用的是 Son print
 obj.show();  // 这个调用会报错! 




Father obj = new Son();     编译看左边,运行看右边

   1.当出现“父类引用指向子类对象”的情况时,如果子类中重写了父类中的一个方法,那么父类引用在调用这个方法的时候,将会调用子类中
    的这个方法(动态绑定、执行);

2.如果你想实现多态,那么必须有三个条件:父类引用,子类对象,方法覆盖;
    这里,如果Fathor类有一个show()方法,那么形成方法覆盖,此时才可以这么写:obj.show()——此刻形成了多态。

3.在没有方法覆盖的情况下,用父类引用去访问一个子类的方法,如上面的show()方法——由于父类引用没有这么大范围的权限,所以会报错;

4.父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是无可奈何的(对于子类中的成员变
量,它也是无法调用的);另外,父类中的一个方法只有在在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用;
【定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。】

5.静态方法是没有多态性的:静态方法不会被子类所覆盖,因此,父类引用只能调用父类的静态方法。

附:一些问题的解答

   A:当父类引用f指向其子类的对象的时候,通过f无法访问专属于子类对象的成员
Q:为什么这样不可以?因为f是FatherClass,所以编译器只知道f拥有FatherClass.class的信息,FatherClass.class以外的信息,编译器
不知道,而子类的对象成员是在SonClass.class里,也就是说在FatherClass.class以外,所以f无法访问子类的对象成员。

A:假如子类中有对父类方法的重写,那么根据多态机制,通过f访问这个方法的时候实际访问的是子类中重写的方法。
Q:为什么这样可以?上面说了,f只能访问FatherClass.class的信息(注意这里指的是编译期编译器只知道f是FatherClass类型,不知道f
具体指向什么对象,运行期才知道指向什么对象),而子类重写的方法,父类中也存在,即SonClass.class重写的方法,FatherClass.class里
也有(如果SonClass.class里有但是FatherClass.class里没有的方法,f也不能直接调用),所以f可以访问,但是调用的时候(注意这里指的
是运行期),f实际指向的是SonClass对象,所以调用的是SonClass对象的方法。

A:如果子类重写的方法中访问了专属于子类的成员变量,这时候通过父类引用f还可以调用那个被重写的方法吗?
Q:可以,要分清编译期和运行期,编译期是编译器检查语法和类型,运行期是解析器解析伪代码为机器指令而执行,编译期编译器会检查f
的访问范围,也就是f的访问不超过FatherClass.class的信息就不会出错,运行期解析器会解析方法的代码指令,因为f指向子类对象,所以会
解析子类重写的方法代码指令,而子类对象的内存空间是包含子类的成员变量的空间的,所以也不存在子类成员变量没有分配内存的问题,所
以可以调用。
0 0
原创粉丝点击