4、面向对象(二)

1、多态

多态简介

多态就是事物存在的多种形态,比如你在大街上看见一只藏獒,你可以说这只藏獒真凶猛,也可以说这只狗真凶猛,还可以说这个动物真凶猛,以上三种说法其实都是指的这只藏獒。
在Java里面,也是存在多态的,只要全部符合下面这三种情况,就是多态

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

例如下面代码就构成多态

class Animal{
    public int num = 10;
    
    public void eat(){
        System.out.println("动物再吃!");
    }
}

class Cat extends Animal{
    public int num = 20;
    public void eat(){
        System.out.println("猫再吃!");
    }
}

class Animal_Text{
    public static void main(String[] args){
        Animal m1 = new Cat();// 父亲引用指向子类对象
        m1.eat(); // 猫在吃 动态绑定和静态绑定
        System.out.println(m1.num); // 10 说明成员变量不存在
    
    }
}

静态绑定和动态绑定

上面代码中,a1是Animal类型的一个引用,指向的是其子类Cat的对象,这个就叫做父类引用指向子类对象。程序在编译的时候a1被看做Animal类型,所以a1.eat()绑定的是Animal类中的eat()方法,这叫做静态绑定,程序运行时,a1指向的是堆中的Cat对象,而在Cat中对eat()方法进行了重写,所以在运行阶段绑定的是Cat中的eat()方法,这叫做动态绑定

强制类型转换

上面代码中子类向父类型进行转换,是自动类型转换,也叫做向上转型。还有一种情况是父类向子类型转换,是强制类型转换,也叫向下转型。下面的代码演示了强制类型转换

class Animal{
    public int num = 10;
    
    public void eat(){
        System.out.println("动物再吃!");
    }
}

class Cat extends Animal{
    public int num = 20;
    public void eat(){
        System.out.println("猫再吃!");
    }
    
    //Cat特有的方法.
    public void move(){
        System.out.println("猫走路很轻盈!");
    }
}


class Dog extends Animal{

    //重写
    public void eat(){
        System.out.println("狗啃骨头!");
    }
}

class Animal_Text{
    public static void main(String[] args){
        Animal a1 = new Cat();// 父亲引用指向子类对象
        //如果要是想执行Cat里面的move方法该怎么办?
        //只能强制类型转换,需要加强制类型转换符
        Cat c1 = (Cat)a1;
        c1.move();

        Animal a2 = new Dog(); //向上转型.
        //强制类型转换
        //Cat c2 = (Cat)a2; //会报错 java.lang.ClassCastException
        
    
    }
}

instanceof关键字

上面的代码里面将一个指向Dog对象的Animal引用a2进行强制转换成Cat类型时报出了ClassCastException类转型错误,开发中要是想避免这种错误需要使用instanceof来判断一下。

class Animal{
    public int num = 10;
    
    public void eat(){
        System.out.println("动物再吃!");
    }
}

class Cat extends Animal{
    public int num = 20;
    public void eat(){
        System.out.println("猫再吃!");
    }
    
    //Cat特有的方法.
    public void move(){
        System.out.println("猫走路很轻盈!");
    }
}


class Dog extends Animal{

    //重写
    public void eat(){
        System.out.println("狗啃骨头!");
    }
}

class Animal_Text{
    public static void main(String[] args){
        Animal a1 = new Cat();// 父亲引用指向子类对象
        //如果要是想执行Cat里面的move方法该怎么办?
        //只能强制类型转换,需要加强制类型转换符
        Cat c1 = (Cat)a1;
        c1.move();

        Animal a2 = new Dog(); //向上转型.
        //进行强制类型转换时,需要先使用instanceof进行判断,避免ClassCastException
        if (a2 instanceof Cat){
            //强制类型转换
            Cat c2 = (Cat)a2;
        }else{
            System.out.println("无法进行强制类型转换");
        }
    }
}

多态的优点

  • 提高了程序的扩展性
  • 降低了代码之间的耦合
class Car{
    public void run(){
        System.out.println("汽车在行驶!");
    }
}

class Benz extends Car{
    public void run(){
        System.out.println("奔驰汽车在跑");
    }
}

class BWM extends Car{
    public void run(){
        System.out.println("宝马汽车再跑!");
    }
}

class Person{
     /*
    public void drive(Benz bc){
        bc.run();
    }
    奔驰汽车坏了,再重新创建一个开宝马汽车的方法
    public void drive(BMW bm){
        bm.run();
    }
    */

    //上面代码扩展性太差,每新增加一种品牌的汽车就需要再写一个方法
    //将参数修改为Car类型,这样不论增加什么样的品牌汽车,都可以调用这个方法
    public void driver(Car c){
        c.run();
    }
}

public class Test{
    public static void main(String[] args){
        Person james = new Person();

        //Benz bc = new Benz();
        //james.drive(bc);

        BMW bm = new BMW();    
        james.drive(bm);
    
    }
}

猜你喜欢

转载自www.cnblogs.com/zhuifeng-mayi/p/10019319.html