多态性是面向对象编程的又一个重要特征,那么多态是什么呢?

一、多态的概念

1.概念:多态是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,这使得同一个属性或方法在父类及其各个子类中具有不同的含义。

2.多态现实意义的理解:多态是同一个行为具有多个不同表现形式或形态的能力;多态就是同一个接口,使用不同的实例而执行不同操作。

(1)现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。                                                                                                            

(2)Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。

二、多态的使用

1.多态的使用前提:

java实现多态有 3 个必要条件:继承、重写和向上转型。

(1)继承:在多态中必须存在有继承关系的子类和父类。

(2)方法重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。

(3)向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法。即父类引用变量可以指向子类对象。

父类类型 变量名=new 子类类型();

2.示例:接下来我们用代码来帮助理解

父类:Animal类

public class Animal {

public String name;

public int health;//健康值

public int love;//亲密度

public Animal() {//无参构造

super();

}

public Animal(String name, int health, int love) {//有参构造

super();

this.name = name;

this.health = health;

this.love = love;

}

//定义一个方法

public void test(){

System.out.println("我是Animal类中的test()方法");

}

}

子类:Cat类

public class Cat extends Animal {

public String color;//颜色

public Cat() {

super();

}

public Cat(String name, int health, int love, String color) {

super(name, health, love);

this.color = color;

}

// 重写Animal类中的test()方法

public void test() {

System.out.println("我是Cat类中的test()方法");

}

public void play(){

System.out.println("我是Cat类中的play()方法");

}

}

子类:Dog类

public class Dog extends Animal {

public String strain;//种类

public Dog() {

super();//调用父类Animal类中的无参构造方法

}

public Dog(String name, int health, int love, String strain) {

super(name, health, love);//调用父类Animal类中的有参构造方法

this.strain = strain;

}

//重写Animal类中的test()方法

public void test(){

System.out.println("我是Dog类中的test()方法");

}

public void eat(){

System.out.println("我是Dog类中的eat()方法");

}

}

测试:Test类

public class Test {

public static void main(String[] args) {

//创建Dog类对象

Dog dog = new Dog("旺财", 100, 100, "金毛");

dog.test();

//创建Cat类对象

Cat cat = new Cat("Tom", 100, 99, "蓝色");

cat.test();

System.out.println("--------------------------");

//多态:同一个父类引用,指向不同的子类实例,执行不同的操作。方法重写是实现多态的前提

//向上转型(自动类型转换):父类的引用指向子类的实例(对象)

Animal animal = new Dog("来福", 100, 98, "泰迪");

animal.test();

//eat()方法是Dog类中独有的方法、父类引用无法直接调用子类中特有的方法,如果父类引用需要使用子类中独有的的方法,需要将父类引用强制类型转换为子类

// animal.eat();

//向下转型(强制类型转换):子类的引用指向父类的引用

Dog dog2=(Dog)animal;

dog2.eat();

animal = new Cat("加菲猫", 85, 88, "黄色");

animal.test();

//play()方法是Cat类中独有的方法,父类引用无法直接调用子类中特有的方法,如果父类引用需要使用子类中独有的的方法,需要将父类引用强制类型转换为子类

// animal.play();

//在向下转型过程中,容易出现类型转换异常ClassCastException,将父类引用转换成了其它的子类对象,所以在转换之前需要对父类引用类型进行判断

// Dog cat2 =(Dog)animal;

if(animal instanceof Dog){

Dog dog3 =(Dog)animal;

dog3.eat();

}else if(animal instanceof Cat){

Cat cat3 =(Cat)animal;

cat3.play();

}

}

}

结果:

由上述代码我们可以看到,创建了一个Animal引用指向Dog类实例,然后使用animal引用调用test()方法,实际上调用的却是Dog类中的test()方法,这就是多态的一种应用;

三、Java中实现和使用多态的主要方式:

1.使用父类作为方法的形参:

示例:

父类:Animal类

public class Animal {

private String name;

private int health;//健康值

private int love;

public Animal() {

super();

}

public Animal(String name, int health, int love) {

super();

this.name = name;

this.health = health;

this.love = love;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getHealth() {

return health;

}

public void setHealth(int health) {

this.health = health;

}

public int getLove() {

return love;

}

public void setLove(int love) {

this.love = love;

}

//定义一个方法实现Animal看病

public void lookDoctor(){

System.out.println("我是Animal类中看病的lookDoctor()方法");

}

}

子类:Cat类

public class Cat extends Animal {

private String color;

public Cat() {

super();

}

public Cat(String name, int health, int love, String color) {

super(name, health, love);

this.color = color;

}

public String getColor() {

return color;

}

public void setColor(String color) {

this.color = color;

}

//重写Animal类中的lookDoctor()方法

@Override

public void lookDoctor() {

System.out.println("猫生病了,打针和吃药.....");

this.setHealth(85);

}

}

子类:Dog类

public class Dog extends Animal {

private String strain;

public Dog() {

super();//调用父类Animal类中的无参构造方法

}

public Dog(String name, int health, int love, String strain) {

super(name, health, love);//调用父类Animal类中的有参构造方法

this.strain = strain;

}

public String getStrain() {

return strain;

}

public void setStrain(String strain) {

this.strain = strain;

}

//重写Animal类中的lookDoctor()方法

@Override

public void lookDoctor() {

//健康值小于60的时候

System.out.println("狗生病了,打针.......");

this.setHealth(70);

}

}

子类:Penguin类

public class Penguin extends Animal {

private char sex;

public Penguin() {

super();

}

public Penguin(String name, int health, int love, char sex) {

super(name, health, love);

this.sex = sex;

}

public char getSex() {

return sex;

}

public void setSex(char sex) {

this.sex = sex;

}

// 重写Animal类中的lookDoctor()方法

@Override

public void lookDoctor() {

// 健康值小于60的时候

System.out.println("企鹅生病了,吃药.......");

this.setHealth(75);

}

}

主人类:Master类

public class Master {

//定义给Animal对象看病的方法

public void cure(Animal animal){

//animal对象健康值小于60的时候需要看病

if(animal.getHealth()<60){

animal.lookDoctor();

}

}

}

测试类:Test类

public class Test {

public static void main(String[] args) {

Master master = new Master();

//创建Dog类对象

Dog dog1 = new Dog("旺财", 30, 99, "藏獒");

System.out.println(dog1.getHealth());

//调用方法原则一:方法需要什么类型的参数就需要给什么类型的参数---》方法需要什么类型的参数就需要给什么类型的参数(包括其子类)

master.cure(dog1);

System.out.println(dog1.getHealth());

System.out.println("----------------");

//创建Penguin类对象

Penguin penguin1 = new Penguin("QQ", 45, 90, '母');

System.out.println(penguin1.getHealth());

master.cure(penguin1);

System.out.println(penguin1.getHealth());

System.out.println("----------------");

Animal animal = new Dog("来福", 20, 100, "拉布拉多");

System.out.println(animal.getHealth());

master.cure(animal);

System.out.println(animal.getHealth());

System.out.println("---------------------------------");

animal = new Penguin("QQ", 50, 92, '公');

System.out.println(animal.getHealth());

master.cure(animal);

System.out.println(animal.getHealth());

}

}

结果:

 可以看到在Master类中将Animal类对象作为一个形参,来进行方法的调用;

2.使用父类作为方法的返回值:

父类:Animal类

public abstract class Animal {

//定义一个动物叫的方法

public abstract void shout();

}

子类:Cat类

public class Cat extends Animal {

@Override

public void shout() {

System.out.println("喵喵喵");

}

}

子类:Dog类

public class Dog extends Animal {

@Override

public void shout() {

System.out.println("汪汪汪");

}

}

主人类:Master类

public class Master {

//将父类Animal作为方法的形参使用,是多态的使用方式之一

//定义一个方法:实现让动物叫

public void letShout(Animal animal){

animal.shout();

}

//将父类Animal作为方法的返回值,也是多态的使用方式之一

public Animal giveAnimal(String type){

Animal animal = null;

if(type.equals("狗")){

animal = new Dog();

}else{

animal = new Cat();

}

return animal;

}

}

测试类:Test类

public class Test {

public static void main(String[] args) {

Master master = new Master();

// Animal是抽象类。不能直接实例化,可以使用多态的形式,将animal引用指向子类实例

// Animal animal = new Animal();

Animal animal = new Dog();

master.letShout(animal);

animal = new Cat();

master.letShout(animal);

System.out.println("-----------------------");

//赠送动物

Scanner sc = new Scanner(System.in);

System.out.println("你想要什么动物?(猫/狗)");

String pet =sc.next();

Animal ani=master.giveAnimal(pet);

ani.shout();

}

}

可以看到Master类中父类Animal类作为方法的返回值。

四、多态的必要性

使用多态的好处:

1.提高了代码的可维护性

2.可以使程序有良好的扩展,并可以对所有类的对象进行通用处理。

五、多态的局限性

1.当父类引用指向子类对象时,父类引用是不能直接调用子类特有的方法的。需要向下转型(强制类型转换)。

向下转型(强制类型转换)格式:

父类类型 父类对象引用=new 子类类型();//向上转型(自动类型转换):父类的引用指向子类的实例(对象

子类类型  子类对象引用=(子类类型)父类对象引用;//向下转型(强制类型转换):子类的引用指向父类的引用

向下转换后才能调用子类特有的方法。

2.同时,在向下转型的过程中,容易出现类型转换异常ClassCastException,将父类引用转换成了其它的子类对象,所以在转换之前需要对父类引用类型进行判断

这时就需要用到instanceof关键字进行判断

 if(animal instanceof Dog){             Dog dog =(Dog)animal;             dog.eat();//Dog类中独有方法         }else if(animal instanceof Cat){             Cat cat =(Cat)animal;             cat.play();//Cat类中独有方法         }

注意:使用instanceof时,对象的类型必须和instanceof后面的参数所指定的类在继承上有上下级关系。

 

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: