面向对象的重要特性之多态!

**多态是面向对象的一个重要特性!**那么我们来认知一下什么是多态。

一、什么是多态

在程序设计的术语中,它意味着一个特定类型的变量可以引用不同类型的对象,并且能够自定地调用引用的对象方法,也就是根据作用到的不同对象类型,响应不同的操作。方法重写是实现多态的基础。

二、简单示例认识多态

下面通过这个例子简单认识多态
有宠物类父类(Pet),有几个子类(Bird)、(Dog)等宠物类定义了看病的方法toHospital(),子类分别重写了看病的方法。在main方法中分别实例化各种具体的宠物,并调用看病的方法。

代码实现
1.编写父类

//父类Pet
public class Pet {
    public void toHospital(){
        System.out.println("宠物看病!");
    }
}

2.写子类小狗

public class Dog extends Pet {
    public void toHospital(){
        System.out.println("小狗看病");
    }
}

3.写子类小鸟

//小鸟子类继承父类
public class Bird extends Pet{
    public void toHospital(){
        System.out.println("小鸟看病");
    }
}

4.写创建对象测试类得到输出结果

//测试类
public class Text {
    public static void main(String[] args) {
        Dog d =new Dog();
        Bird b = new Bird();
        d.toHospital();//狗狗看病
        b.toHospital();//小鸟看病
    }
}

输出结果:
小狗看病
小鸟看病

5.运用多态性测试类得输出结果

        public class Text {
    public static void main(String[] args) {
	Pet pet;
        pet = new Dog();
        pet.toHospital();
        pet = new Bird();
        pet.toHospital();
    }
}

虽然步骤5中的代码定义的是Pet类,但实际执行时调用的都是Pet子类的方法,这就体现了多态性。这就说明了多态意味着在一次方法调用中根据包含的对象的实际类型(即实际的子类对象)来决定应该调用哪个方法,为了实现多态的操作,这个方法既是在父类中声明过的,也必须是在子类中重写过的方法。

这时候应该对多态有了一个大概的认识吧

三、向上转型与向下转型

1.向上转型:
子类向父类的转型称为向上转型
向上转型的语法格式如下:
<父类型><引用变量名>=new <子类型>();
如:Pet pet = new Dog();
这时候Pet类调用子类的toHospital()方法,而不是Pet类的toHospital()方法,这就体现了多态性。

总结规则:

  1. 将一个父类的引用指向一个子类对象称为向上转型,系统会自动进行类型转换
  2. 此时通过父类引用变量调用的方法是子类覆盖或继承了父类的方法,不是父类的方法
  3. 此时通过父类引用变量无法调用子类特有的方法

2.向下转型
向上转型中父类引用变量无法调用子的特有方法,这时候我们就可以将父类转换为子类来实现子类特有的方法。

向下转型释义:将一个指向子类对象的父类引用赋给一个子类的引用,即将父类类型转换为子类类型,称为向下转型,此时必须进行强制类型转换。

比如我们在Dog类中添加一个特有的接飞盘方法catching(),如果不转型就不出现无法调用的问题,可以这么理解,主人可以为各种宠物看病,但接飞盘只能与狗狗一起玩。这时候直接调用子类方法,就会有可能调用到鸟类中,所以需要进行强制转换才能够调用子类的特有方法。

向下转型的语法:
<子类型><引用变量名>=(<子类型>)<父类型的引用变量名>

如:
Dog dog = (Dog) pet;
dog.catching();//执行Dog的特有方法。

上述这种向下转型的操作对接口和抽象(普通)父类同样适用

四、instanceof运算符

在向下转型的过程中,如果不是转换为真实子类类型,会出现类型转换异常
instanceof运算符:进行类型的判断来进行向下转换

代码实现:

//分别在小鸟和小狗类中添加了特有的方法
public class Text {
    public static void main(String[] args) {
	 Pet pet;
        pet=new Bird();
        pet.toHospital();
//        pet = new Dog();
//        pet.toHospital();
        if (pet instanceof Dog){
            Dog dog =(Dog) pet;
            dog.catching();
        }else if (pet instanceof Bird){
            Bird bird = (Bird)pet;
            bird.fly();
        }
    }
}

输出结果:
小鸟看病
小鸟飞翔

注意:使用instanceof时,对象的类型必须和instanceof后面的参数所指定的类有继承关系,否则会出现编译错误,instanceof通常和强制类型转换结合使用

五、多态的优势

结合上面的代码和知识点,我们可以看出多态的优势非常突出!

  1. 可替换性:多态对已存在的代码具有可替换性
  2. 可扩充性:多态对代码具有可扩充性。增加新的子类不影响已经存在类的多态性和继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。
  3. 接口性:多态是父类向子类提供了一个共同接口,由子类来具体实现。
  4. 灵活性:多态在应用中体现了灵活多样的操作,提高了使用效率
  5. 简化性:多态简化了应用软件的的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要

六、多态的应用

在多态的程序设计中,一般有以下两种主要的应用形式。

1.使用父类作为方法的形参
这是java中实现和使用多态的主要方式。

代码演示

1.有父类Animal

package demo;

public class Animal {
    public void cry(){
        System.out.println("宠物叫");
    }
}

2.有Host类控制宠物叫的方法

package demo;
//主人类
public class Host {
    public void letCry(Animal animal){
        animal.cry();
    }
}

3.有子类Dog类为叫的方法

package demo;

public class Dog extends Animal {
    public void cry(){
        System.out.println("狗叫");
    }
}

4.测试类调用代码

package demo;

public class Test {
    public static void main(String[] args) {
        Host host =new Host();
        Animal animal;
        animal =new Dog();
        host.letCry(animal);

    }

}
输出结果:狗叫

在这个示例中并没有把动物的子类作为方法参数,而是使用Animal父类。当调用letCry方法时,实际传入的参数是一个子类的动物,最终调用的也是这个子类动物的cry方法。

2.使用父类作为方法的返回值
java中实现和使用多态的主要方式之二

代码演示:
1.host类

//主人类
public class Host {
   public Animal donate(String type){
        Animal animal;
        if (type == "dog"){
            animal = new Dog();
        }else {
            animal= new Cat();
        }
        return animal;
    }
}

2.新增cat类

package demo;
public class Cat extends Animal{
    public void cry(){
        System.out.println("猫叫");
    }
}

3.重新编辑测试类

package demo;

public class Test {
    public static void main(String[] args) {
        Host host =new Host();
        Animal animal;
        animal =host.donate("dog");
        animal.cry();
        animal= host.donate("cat");
        animal.cry();

    }

}
输出结果:
狗叫
猫叫

在上述代码中将父类Animal作为返回值,而不是具体的子类,调用者仍然可以控制动物叫,动物的行为则由具体的动物类型决定。

ok,多态就讲到这里,后续会提供一些练习来巩固知识!

猜你喜欢

转载自blog.csdn.net/weixin_42507474/article/details/107400286