Java 多态

多态

多态基本介绍

方法或对象具有多种形态。是面向对象的三大特征,多态是建立在封装和继承基础之上的。

多态的具体体现

1、方法的多态: 重写和重载就能体现多态。

2、对象的多态:【背下来,记住】

  • 一个对象的编译类型和运行类型可以不一致

  • 编译类型在定义对象时,就已经被确定,不能再改变

  • 运行类型是可以变化的

  • 编译类型看定义时 = 号的左边,运行类型看 = 号的右边

// 可以让父类的引用指向子类的类型。
Animal animal = new Dog(); //animal编译类型是Animal, 运行类型是Dog  
animal = new Cat();    // animal的运行类型变成了Cat,编译类型仍然为Animal

多态的注意事项和细节讨论

多态的前提是:

1、两个对象(类)存在继承关系。

2、多态的向上转型

3、多态的向下转型

4、类的属性没有重写之说,当调用类的属性时,属性的值为编译类型对应的值,如果在编译类型中没有查到,则去父类中查找属性

package com.encap.poly;

public class PolyDetail {
  public static void main(String[] args) {
      Animal animal = new Dog();
      // 判断运行结果
      System.out.println(animal.count);
  }
}

class Animal{
  int count = 10;
}

class Dog extends Animal{
  int count = 20;
}

5、instanceOf比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX类型的子类型

String str = "hello";
str isstanceOf Object;    // true。   判断对象的运行类型【String】 是否为 XXX(Object)类型或 XX(Object)类型的子类型。

什么叫向上转型:

1、本质:父类的引用指向了子类的对象

2、语法:父类类型 引用名 = new 子类类型();

Animal animal = new Cat();

3、使用特点:

  • 编译类型看左边,运行类型看右边。

  • 可以调用父类中的所有成员(需遵循父类的访问权限)

  • 不能调用子类中的特有成员

对上面两句的解释:在编译阶段,能调用哪些成员,是由编译类型来决定的。javac指令

  • 最终运行效果看运行类型的具体实现。 即调用成员时,按照从子类(运行类型)开始查找成员,找到则调用,找到没权限则报错。 java指令

向下转型

1、语法: 子类类型 引用名 = (子类类型) 父类引用;

Cat cat = (Cat)animal;

2、只能强转父类的引用,不能强转父类的对象。

3、要求父类的引用必须指向的是当前目标类型的对象

4、当向下转型后,可以调用子类类型中的所有成员

Animal animal = new Cat();   // 向上转型,子类的对象,指向父类的引用名
Cat cat = (Cat)animal;   // 向下转型, 将父类的引用进行强转,转成 当前目标类型的对象。    
// animal此引用名指向堆中的Cat类,这是向上转型,此时编译类型为Animal,但运行类型为 Cat    
// 向下转型则为,将堆中的Cat类重新创建一个引用,所以要求父类的引用必须指向的是当前目标类型的对象。

动态绑定机制

1、当调用对象方法的时候,该方法会对该对象的内存地址/运行类型进行绑定。即为方法从运行类型开始查找。

2、当调用对象属性时,则没有动态绑定机制,即为,属性哪个编译类调用,就用哪个编译类的属性

在这里插入图片描述

第二点是在方法中使用到属性,所以是对应着声明类。

「多态的前提」是,「类的属性没有重写之说,当调用类的属性时,属性的值直接对应编译类型得到,如果编译类型中没有,则去父类中查找属性」 。属性没有重写机制,则不需要从子类向父类查找属性,记住这两种情况即可。

测试题

package com.encap.test;

public class Test {
    public static void main(String[] args) {
        A a = new B();
        System.out.println(a.getSum()); 
        System.out.println(a.getSum1()); 
    }
}

class A {
    public int i = 10;

    public int getI() {
        return i;
    }

    public int getSum() {
        return getI() + 10;
    }

    public int getSum1() {
        return i + 10;
    }

}

class B extends A{
    public int i = 20;

    public int getI() {
        return i;
    }

//    public int getSum() {
//        return getI() + 20;
//    }

//    public int getSum1() {
//        return i + 10;
//    }
}

多态数组

多态数组的定义类型为父类类型,里面保存的实际元素类型为子类类型。

package com.encap.extend_.Exercise03;

public class Test {
    public static void main(String[] args) {
        PC pc = new PC("inter", 16, 256, "IBM");

//        创建多态数组方法一:
//        Computer[] c = new Computer[2];
//        c[0] = pc;
//        c[1] = new Computer("Mac", 256, 512);
        // 创建多态数组方法二:
        Computer[] c = {pc, new Computer("Mac", 256, 512)};
        for (int i = 0; i < c.length; i++) {
            if (c[i] instanceof PC){
                // 向下转型方法一:
                ((PC)c[i]).printInfo();
                // 向下转型方法二:
//                PC p1 = (PC)c[i];
//                p1.printInfo();
            } else{
                System.out.println(c[i].getDetail());
            }
        }
    }
}


class PC extends Computer{
    private String brand;

    public PC(String CPU, int memory, int disk, String brand) {
        super(CPU, memory, disk);
        this.brand = brand;
    }

    public void printInfo(){
        System.out.println("PC信息为:");
        System.out.println(getDetail() + "品牌为: " + brand);
    }
}

class Computer {
    private String CPU;
    private int memory;
    private int disk;

    public Computer(String CPU, int memory, int disk) {
        this.CPU = CPU;
        this.memory = memory;
        this.disk = disk;
    }

    public String getDetail(){
        return "电脑的详细信息:" + "CPU: " + CPU + " 内存为: " + memory  + " 硬盘为:" + disk;
    }
}


多态参数

方法定义的形参类型为父类类型,实参类型则允许传入子类类型。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值