Java 多态

一,多态的概念

注:多态是指对象(具体),而不是指类(抽象)。

二,多态的格式和使用

代码当中体现多态性,其实就是一句话:父类引用指向子类对象。(左父右子
格式:父类名称 对象名 = new 子类名称();
      或者:
     接口名称 对象名 = new 实现类名称()
public class Fu {
    public void method() {
        System.out.println("父类方法");
    }
    public void methodFu() {
        System.out.println("父类特有方法");
    }
}

 注:

public class Zi extends Fu {
    @Override
    public void method() {
        System.out.println("子类方法");
    }
}
public class Demo01Multi {
    public static void main(String[] args) {
        // 使用多态的写法
        // 左侧父类的引用,指向了右侧子类的对象

        Fu obj = new Zi();

        obj.method();    //打印输出:子类方法
        obj.methodFu();  //打印输出:父类特有方法
    }
}

注:“Fu obj = new Zi(); ”中体现了多态,调用对象的方法时,右侧new的谁就运行谁。若子类没有,再找父类。

三,多态中成员变量的使用

访问成员变量的两种方式:
1. 直接通过对象名称访问成员变量:看等号左边是谁,优先用谁,没有则向上找。
2. 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,没有则向上找
public class Fu  {
    int num = 10;
    public void showNum() {
        System.out.println(num);
    }
}
public class Zi extends Fu {
    int num = 20;
    int age = 16;
    @Override
    public void showNum() {
        System.out.println(num);
    }
}
public class Demo01MultiField {
    public static void main(String[] args) {
        // 使用多态的写法,父类引用指向子类对象
        Fu obj = new Zi();

//1)通过对象访问成员变量

        System.out.println(obj.num); // 父:10
//        System.out.println(obj.age); // 错误写法!

//2)通过成员方法访问成员变量

        // 子类没有覆盖重写,就是父:10
        // 子类如果覆盖重写,就是子:20
        obj.showNum();
    }
}

注意:错误写法 “System.out.println(obj.age);”,因为父类中没有成员变量age,只能向上Object类找(也没有),不能向下子类中找。所以该语句会报错!!!

四,多态中成员方法的使用特点

在多态的代码当中,成员方法的访问规则是:
    看new的是谁,就优先用谁,没有则向上找。

总结:成员变量看左,成员方法看右。

public class Fu  {
    public void method() {
        System.out.println("父类方法");
    }
    public void methodFu() {
        System.out.println("父类特有方法");
    }
}
public class Zi extends Fu {
    @Override
    public void method() {
        System.out.println("子类方法");
    }
    public void methodZi() {
        System.out.println("子类特有方法");
    }
}
public class Demo02MultiMethod {
    public static void main(String[] args) {
        Fu obj = new Zi(); // 多态

//父子都有,优先用子
        obj.method(); // 打印输出:子类方法

//子类没有,父类有,向上找到父类
        obj.methodFu(); // 打印输出:父类特有方法

//        obj.methodZi(); // 错误写法!
    }
}

注:obj.methodZi是错误写法! 

五,使用多态的好处

 六,对象的上下转型

1.向上转型

示例:

public abstract class Animal {
    public abstract void eat();
}
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}

弊端:

解决方案:用对象的向下转型【还原】

2.向下转型

1)什么时候要向下转型:想要使用子类专有方法时。

public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃SHIT");
    }

    public void watchHouse() {
        System.out.println("狗看家");
    }
}
public class Demo01Main {

    public static void main(String[] args) {
        // 对象的向上转型,就是:父类引用指向之类对象。
        Animal animal = new Cat(); // 本来创建的时候是一只猫
        animal.eat(); // 猫吃鱼

//        animal.catchMouse(); // 错误写法!

        // 向下转型,进行“还原”动作
        Cat cat = (Cat) animal;
        cat.catchMouse(); // 猫抓老鼠

        // 下面是错误的向下转型
        // 本来new的时候是一只猫,现在非要当做狗
        // 错误写法!编译不会报错,但是运行会出现异常:
        // java.lang.ClassCastException,类转换异常
        Dog dog = (Dog) animal;
    }

}

 2)格式:

原本的向上转型(多态的实现):

Animal animal = new Cat();

由于想使用子类Cat类中的catchMouse子类专有方法,所以要转回去——把本来是Animal父类的对象animal转为Cat子类,并将对象重命名为cat。

Cat cat = (Cat) animal;

 3)向下转型的条件

注:向下转型不一定安全。只能将之前向上转型的转回来。若之前没有发生过向上转型,则该对象不可实现向下转型。

 注:没有创建狗的对象,却向下转型为狗,则会报“类转型错误”的异常。

3.instanceof关键字:用于判断父类引用的是哪个子类

public class Demo02Instanceof {

    public static void main(String[] args) {
        Animal animal = new Dog(); // 本来是一只狗
        animal.eat(); // 狗吃SHIT

        // 如果希望掉用子类特有方法,需要向下转型
        // 判断一下父类引用animal本来是不是Dog
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        // 判断一下animal本来是不是Cat
        if (animal instanceof Cat) {
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }

        giveMeAPet(new Dog());
    }

    public static void giveMeAPet(Animal animal) {
        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        if (animal instanceof Cat) {
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }
    }
}

注:这段断码段为常用固定写法,用于判断,防止报错。 

        if (animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.watchHouse();
        }
        // 判断一下animal本来是不是Cat
        if (animal instanceof Cat) {
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值