Java基础 — 多态

概述
  • 一个对象对应多种类型
  • 同一个行为具有多个不同表现形式或形态的能力
  • 多态在代码中的体现:父类或接口的引用指向其子类对象
利弊

好处:

  • 提高代码的可扩展性,方便后期维护 (后期添加的子类对象可使用前期父类或接口定义的方法)

弊端:

  • 子类特有的方法无法被父类/接口的引用对象所调用
`PolymorphismDemo.java`

abstract class Animal{
    public abstract void eat(); 
} 

class Cat extends Animal{
    public void eat(){
        System.out.println("cat eat");
    }
    public void catchMouse(){
        System.out.println("cat catch mouse");
    }
}

class Dog extends Animal{
    public void eat(){
        System.out.println("dog eat");
    }
    public void protectHome(){
        System.out.println("dog protect home");
    }
}

class PolymorphismDemo{
    public static void main(String[] args){
        Cat c = new Cat();
        Dog d = new Dog();
        // c.eat();
        // d.eat();
        // 提高代码复用性——method()
        method(c);
        method(d);
    }
    /*
    public static void method(Cat c){
        c.eat();
        c.catchMouse();
    }
    public static void method(Dog d){
        d.eat();
    }
    // 为子类的引用,后期出现新的子类对象则需要添加对应的新的方法
    */
    
    // 父类的引用,则后期新的对象只要属于其子类皆可使用之前的方法
    public static void method(Animal a){
        a.eat();
        // a.catchMouse(); ————>wrong (子类特有方法)
    }
}

前提:

  • 对象与类型要有关系———继承、实现
  • 要有覆写(重写) – Override
向上、向下转型
缘由
  • 向上转型:提高程序扩展性,限制对特有功能的访问
  • 向下转型:为了使用子类中的特有方法
  • 仅是对同一子类对象的类型转换
// 续 PolymorphismDemo.java

// 1.向上转型
    
Animal a = new Cat(); 
//类似自动类型提升
a.eat(); // 但无法访问特有功能

// 2.向下转型
    
Cat c = (Cat)a; 
c.eat();
c.catMouse(); // 为了使用子类的特有功能

// 注意:
// 对于转型,只涉及同一子类对象类型的转换

Animal a1 = new Dog();
Cat c1 = (Cat)a1; //————wrong
//ClassCastException 类型转换错误
转型后,父类子类、静态非静态方法/属性 调用问题
  1. 父类Animal
public class Animal {
    public String name = "父类Animal共同非静态属性:name";
    public static String staticName = "父类Animal静态属性:staticName";

    public void eat() {
        System.out.println("父类Animal共同非静态方法:eat()");
    }

    public static void staticEat() {
        System.out.println("父类Animal共同静态方法:staticEat()");
    }
}
  1. 子类Pig
public class Pig extends Animal {
    public String name = "子类Pig共同非静态属性:name";
    public static String staticName = "子类Pig共同静态属性:staticName";
    public String str = "子类Pig独有非静态属性:str";
   

    public void eat() {
        System.out.println("子类Pig共同非静态方法:eat()");
    }

    public static void staticEat() {
        System.out.println("子类Pig共同静态方法:staticEat()");
    }

    public void pigEat() {
        System.out.println("子类Pig独有非静态方法:eatMethod()");
    }

    public static void main(String[] args) {
        // 1. 向上转型
        Animal animal = new Pig(); 
        
        animal.eat();  // 子类Pig共同非静态方法:eat()
        
        animal.staticEat(); // 父类Animal共同静态方法:staticEat()
        
        //animal.pigEat(); // 编译出错,The method eatMethod() is undefined for the type Animal -- 父类无法使用子类独有方法
        
        System.out.println(animal.name); // 父类Animal共同非静态属性:name
        
        System.out.println(animal.staticName); // 父类Animal静态属性:staticName
        
        System.out.println(animal.staticAlone); // 父类Animal独有静态属性:staticAlone
        
        //System.out.println(animal.str); // 编译出错,str cannot be resolved or is not a field -- 父类无法使用子类独有属性
        
        
        
        // 2. 向下转型
        Pig pig = (Pig) animal; 
        
        System.out.println(pig.name); // 子类Pig共同非静态属性:name
        
        System.out.println(pig.staticName); // 子类Pig共同静态属性:staticName        
        System.out.println(pig.str); // 子类Pig独有非静态属性:str
        
        pig.pigEat(); // 子类Pig独有非静态方法:eatMethod()
        
        pig.staticEat(); // 子类Pig共同静态方法:staticEat()
    }
}
  • 类 – 编译时确定,实例 – 运行时确定 (后面)

  • 向上转型后,引用变量属于父类,静态方法和属性 – 使用父类(父类中一定要存在对应属性或非静态方法,否则编译失败,即使子类存在对应变量),非静态方法 – 如果子类覆写该方法(即子类中存在同名方法),优先使用子类,否则使用父类

  • 向下转型后,引用变量属于子类,同时子类继承父类方法(子类会继承父类所有属性和方法(静态和非静态都继承)),所以无论静态非静态,都优先使用子类,子类不存在,再使用父类方法或属性(静态非静态都可)

  • 向上转型特点 (编译运行区别) – Java – 属性和静态非静态方法 编译时和运行时的区别

对象类型判断
  • 关键字——instanceof

  • 用于判断子类对象的具体类型,只能用于引用数据类型判断

public static void method(Animal a){
    a.eat();
    if(a instanceof Cat){
        Cat c = (Cat)a;
        c.catchMouse();
    }
    else if(a instanceof Dog){
        Dog d = (Dog)a;
        d.protectHome();
    }
    // a instanceof Animal==True
}


注意

  • 如您发现本文档中有错误的地方,
  • 或者您发现本文档中引用了他人的资料而未进行说明时,请联系我进行更正。
  • 转载或使用本文档时,请作说明。
  • 非常感谢:)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值