十一:多态

1概括

多态是继封装、继承之后,面向对象的第三大特性

以继承为前提
2多态的形式和体现
1、多态引用

Java规定父类类型的变量可以接收子类类型的对象,这一点从逻辑上也是说得通的。

父类类型 变量名 = 子类对象;

父类类型:指子类继承的父类类型,或者实现的父接口类型。

所以说继承是多态的前提

2、多态引用的表现

表现:编译时类型与运行时类型不一致,编译时看“父类”,运行时看“子类”。

3、多态引用的好处和弊端

弊端:编译时,只能调用父类声明的方法,不能调用子类扩展的方法;

好处:运行时,看“子类”,如果子类重写了方法,一定是执行子类重写的方法体;变量引用的子类对象不同,执行的方法就不同,实现动态绑定。代码编写更灵活、功能更强大,可维护性和扩展性更好了。

实列

public class Pet {
    private String nickname;
​
    public String getNickname() {
        return nickname;
    }
​
    public void setNickname(String nickname) {
        this.nickname = nickname;
    }
​
    public void eat(){
        System.out.println(nickname + "吃东西");
    }
}
package com.haogu.polymorphism.grammar;
​
public class Cat extends Pet {
    //子类重写父类的方法
    @Override
    public void eat() {
        System.out.println("猫咪" + getNickname() + "吃鱼仔");
    }
​
    //子类扩展的方法
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}
package com.haogu.polymorphism.grammar;
​
public class Dog extends Pet {
    //子类重写父类的方法
    @Override
    public void eat() {
        System.out.println("狗狗" + getNickname() + "啃骨头");
    }
​
    //子类扩展的方法
    public void watchHouse() {
        System.out.println("看家");
    }
}
package com.haogu.polymorphism.grammar;
​
public class TestPet {
    public static void main(String[] args) {
        //多态引用
        Pet pet = new Dog();
        pet.setNickname("小白");
​
        //多态的表现形式
        /*
        编译时看父类:只能调用父类声明的方法,不能调用子类扩展的方法;
        运行时,看“子类”,如果子类重写了方法,一定是执行子类重写的方法体;
         */
        pet.eat();//运行时执行子类Dog重写的方法
//        pet.watchHouse();//不能调用Dog子类扩展的方法
​
        pet = new Cat();
        pet.setNickname("雪球");
        pet.eat();//运行时执行子类Cat重写的方法
    }
}

3 应用多态解决问题

1、声明变量是父类类型,变量赋值子类对象
  • 方法的形参是父类类型,调用方法的实参是子类对象

  • 实例变量声明父类类型,实际存储的是子类对象

package com.haogu.polymorphism.grammar;
​
public class OnePersonOnePet {
    private Pet pet;
    public void adopt(Pet pet) {//形参是父类类型,实参是子类对象
        this.pet = pet;
    }
    public void feed(){
        pet.eat();//pet实际引用的对象类型不同,执行的eat方法也不同
    }
}
package com.haogu.polymorphism.grammar;
​
public class TestOnePersonOnePet {
    public static void main(String[] args) {
        OnePersonOnePet person = new OnePersonOnePet();
​
        Dog dog = new Dog();
        dog.setNickname("小白");
        person.adopt(dog);//实参是dog子类对象,形参是父类Pet类型
        person.feed();
​
        Cat cat = new Cat();
        cat.setNickname("雪球");
        person.adopt(cat);//实参是cat子类对象,形参是父类Pet类型
        person.feed();
    }
}
2、数组元素是父类类型,元素对象是子类对象
package com.haogu.polymorphism.grammar;
​
public class OnePersonManyPets {
    private Pet[] pets;//数组元素类型是父类类型,元素存储的是子类对象
​
    public void adopt(Pet[] pets) {
        this.pets = pets;
    }
​
    public void feed() {
        for (int i = 0; i < pets.length; i++) {
            pets[i].eat();//pets[i]实际引用的对象类型不同,执行的eat方法也不同
        }
    }
}
package com.haogu.polymorphism.grammar;
​
public class TestPets {
    public static void main(String[] args) {
        Pet[] pets = new Pet[2];
        pets[0] = new Dog();//多态引用
        pets[0].setNickname("小白");
        pets[1] = new Cat();//多态引用
        pets[1].setNickname("雪球");
​
        OnePersonManyPets person = new OnePersonManyPets();
        person.adopt(pets);
        person.feed();
    }
}
3、方法返回值类型声明为父类类型,实际返回的是子类对象
package com.haogu.polymorphism.grammar;
​
public class PetShop {
    //返回值类型是父类类型,实际返回的是子类对象
    public Pet sale(String type){
        switch (type){
            case "Dog":
                return new Dog();
            case "Cat":
                return new Cat();
        }
        return null;
    }
}
package com.haogu.polymorphism.grammar;
​
public class TestPetShop {
    public static void main(String[] args) {
        PetShop shop = new PetShop();
​
        Pet dog = shop.sale("Dog");
        dog.setNickname("小白");
        dog.eat();
​
        Pet cat = shop.sale("Cat");
        cat.setNickname("雪球");
        cat.eat();
    }
}
4 向上转型与向下转型

向上转型就是利用多态的方式;

向下转型就是利用强制类型转换的方式;

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐