Java的面向对象

11-多态性与虚拟方法调用

2021-07-02 894 1

简介 了解 多态性与虚拟方法调用,重写与重载的区别

多态性(Polymorphism)


    1.理解多态性:可以理解为一个事物的多种形态。

    2.何为多态性:父类的引用指向子类的对象(或子类的对象赋给父类的引用)

    3. 多态的使用:虚拟方法调用

    有了对象的多态性以后,我们在编译期,只能调用父类中声明的方法,但在运行期,我们实际执行的是子类重写父类的方法。当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法,这就是虚拟方法调用。

    我们看源代码时,ctrl + 左键的时候实际找到的是父类的方法,但是程序执行的时候,实际执行的是子类重写父类的方法。

    Java引用变量有两个类型: 编译时类型(父类)和运行时类型(子类)。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。用简短的话进行总结:编译,看左边;运行,看右边。若编译时类型和运行时类型不一致, 就出现了对象的多态性(Polymorphism)

    “看左边” : 看的是父类的引用(父类中所具有的方法,注意父类中不具备子类特有的方法)

    “看右边” : 看的是子类的对象(实际运行的是子类重写父类的方法)

    4.多态性的使用前提:  ① 类的继承关系  ② 方法的重写

    5.对象的多态性,只适用于方法,不适用于属性(属性编译和运行都看左边, 属性是父类的属性)


upfile

//Person.java
package com.ylaihui.oop7;

public class Person {
    	public void eat(){
    		System.out.println("Person eat()...");
    	}
	
	public void show(){
		System.out.println("Person show()...");
	}
}
//Man.java
package com.ylaihui.oop7;

public class Man extends Person {
    	@Override
    	public void eat() {
    		System.out.println("Man eat()...");
    	}
    	public void walk(){
    		System.out.println("Man walk()...");
	}
}
//Women.java
package com.ylaihui.oop7;

public class Women extends Person {
    	public void eat() {
    		System.out.println("Women eat()...");
    	}
}
//PersonTest.java
package com.ylaihui.oop7;

public class PersonTest {
    	public static void main(String[] args) {
    		
    		// 对象的多态性:父类的引用指向子类的对象
    		Person p1 = new Man();
    		Object obj = new Person();
    		
		//多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法 ---虚拟方法调用
		// ctrl + 左键  的 时候 实际找到的是父类的eat方法
		p1.eat();
		// 子类中没有重写show方法,p1调用的 show, 是调用继承父类的方法 show
		p1.show();
		
		// 多态: 编译看左边,运行看右边
//		p1.walk();  // The method walk() is undefined for the type Person
	}
}

虚拟方法调用说明

     正常的方法调用

        Person e = new Person();

        e.getInfo();

        Student e = new Student();

        e.getInfo();

     虚拟方法调用(多态情况下)  运行时行为

        子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父

        类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法

        确定的。

        Person e = new Student();

        e.getInfo(); //调用Student类的getInfo()方法

     编译时类型和运行时类型

        编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。 ——动态绑定

    


重载和重写

    从编译和运行的角度看:

    重载,是指允许存在多个同名方法,而这些方法的参数不同。

    编译器根据方法不同的参数表, 对同名方法的名称做修饰。

    对于编译器而言,这些同名方法就成了不同的方法。 它们的调用地址在编译期就绑定了。

    Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。(子类继承了父类的方法,如果符合重载的规则,那么也可构成重载, 也算是“两同一不同”)

    所以: 对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,

    这称为“早绑定”或“静态绑定”

    而对于多态,只有等到方法调用的那一刻, 解释运行器才会确定所要调用的具体

    方法,这称为“晚绑定”或“动态绑定” 。引用一句Bruce Eckel(Java编程思想、C++编程思想作者)的话: “不要犯傻,如果它不是晚绑定, 它就不是多态。”

    

点赞 1

文章评论

欢迎您:

纸上得来终觉浅,绝知此事要躬行!

112 文章 59134 浏览 3 评论

联系我

  •   QQ:    361352119
  •  Email:  lisimmy@sina.com
  • 微信: