Java 面向对象三大特征之多态

时间:2021-12-05 15:41:24

多态

1、多态:事物的多种状态,polymorphic

  对象的多态性:同一个对象,可能具有不同的名称,同一个对象,有不同的类型的引用指向它。
  本质:同一个物体有不同的名称和描述。 狗 :狗 动物
  类型的多态性:同一个类型,可能具有不同的子类实现,同一个类型引用,有不同的对象实现,
  本质:同一个名字和描述,可以在不同场景下有不同的真实实现。
    动物: 狗 猫 猪

2、多态的前提

  子类继承父类     方法的重写      父类的引用指向子类的对象

Java 面向对象三大特征之多态Java 面向对象三大特征之多态
class Test 
{
    public static void main(String[] args) 
    {
        Person p = new P1();//父类的引用指向子类的对象
        p.run();
    }
}
class Person
{
    public void run(){
        System.out.println("走走走");
    }
}
class P1 extends Person //继承
{
    public void run(){//方法的重写
        System.out.println("跑起来");
    }
}
继承

3、多态中成员变量的访问特点

  编译看左边,运行看左边(编译时看父类是否有该变量的定义,运行时获取到的是父类的结果)

    在子类对象中有一块区域是super区域,存放继承父类的变量和方法,容易理解,变量a的类型是Fu类型,

  因此a.age可以看做是supper.age,所以输出就是Fu.age变量。

4、多态中成员方法的访问特点

  编译看左边,运行看右边(编译时看父类是否定义该方法,运行时运行子类重写的方法)

  动态绑定

    在JVM执行到方法时,会根据这个方法所属变量类型标识符找到该方法的全限定名(包名+类名),

  这里所属变量类型是父类,但是只知道所属变量类型还不能够的,因为无法确定方法的具体位置(非静态

  方法肯定是在堆中),就无法压到栈中执行,因此必须根据父类变量创建的实际对象确定方法的具体位置

  (在堆中寻找),这种在程序执行过程中,通过动态创建的方法表来定位方法的方式,称为动态绑定。

5、多态中静态方法的访问特点

  编译看左边,运行看左边(编译时看父类是否定义该方法,运行时运行父类的方法)

  原因:方法属于类,和父类的方法不属于重写关系

     静态变量:存储在类的字节码中的变量,被所有对象所共享,不随着对象的变化而变化,

          都有相同的值,所以称为静态变量

      静态方法:只会根据引用所属的父类,来决定运行的内容,运行内容,不会随着子类的变化而变化,

         都是引用所属的父类的方法实现,所以称为静态方法。

Java 面向对象三大特征之多态Java 面向对象三大特征之多态
public class Test {

    public static void main(String[] args) {
        Fu f = new Zi();
        System.out.println(f.age);
        f.run();
        f.show();

    }

}
class Fu{
    int age=10;
    public void run() {
        System.out.println("run run run");
    }
    public static void show() {
        System.out.println("show show show");
    }
}
class Zi extends Fu{
    int age=5;
    public void run() {
        System.out.println("go go go");
    }
    public static void show() {
        System.out.println("show time");
    }
}
多态的访问特点

6、向上向下转型

  当想要访问子类中的属性或子类特有的方法时,需要向下转型

  这里有一个instanceof方法,可以进行一次判断

  格式:子类类型 引用名称 = (子类类型)父类类型的引用;

  eg: Zi z = (Zi)f;

  本质:恢复子类原本的访问范围

7、多态的好处

  1、提高了代码的可扩展性

  2、在方法的参数列表中,可以定义父类类型的引用,将来调用的时候,所有的子类类型的对象,

    都可以作为方法的实际参数。

  3、不在方法的参数列表中,就在普通的方法体中,使用父类的类型指向子类的对象,

  也能提高代码的可扩展性。对象的来源非常广泛,不仅仅是new出来的,(还可能是通过反射获取的,

  通过文件读取的,还可能是网络传递的,在写代码的编译阶段,无法知道对象具体的子类类型的)

  需要使用父类类型的引用,操作不知道的子类类型的对象。