2020.12.10

2020.12.10

一, 多态的两种使用方法

1, 父类引用作为方法参数的情况:

问题的引入:顾客到宠物店购买宠物,随机挑选宠物,让宠物叫一声后决定是否购买。

1:pet类中定义sound方法,表示宠物的叫声
public class Pet {
    private String name;
    //创建没有名字的宠物
    public Pet() {
        this.name = "无名氏";
    }
    
    public void sound() {
        //宠物类中需要叫声方法,但是不能发出声音
    }

2:Dog类重写sound方法,实现狗的叫声

public class Dog extends Pet{
    
    @Override
    public void sound() {
        System.out.println("252525252525252525");
    }

3:cat类重写sound方法,实现猫的叫声
public class Cat extends Pet{
    
    @Override
    public void sound() {
        System.out.println("喵喵喵");
    }

4:宠物店卖宠物,让宠物叫一声

public class PetShop {

    public static void petSound(Dog dog) {
        dog.sound();
    }
    public static void petSound(Cat cat) {
        cat.sound();
    }
    public static void main(String[] args) {
        Pet pets[] = new Pet[] {
            new Dog("大黄"),
            new Cat("花花"),
            new Dog("小黄"),
            new Cat("波斯")
        };
        int index = new Random().nextInt(pets.length);
        if(pets[index] instanceof Dog) {
            petSound((Dog)pets[index]);
        }else if(pets[index] instanceof Cat) {
            petSound((Cat)pets[index]);
        }
    }
}
分析:PetShop中为每个子类都定义了petSound方法,表示子类的叫声,如果增加子类会导致添加新的叫声方法,不利于扩展性。

重构:解决办法是定义统一的一个叫声方法,将父类Pet作为方法参数
public class PetShop {

    //父类引用作为方法参数时,可以传入该类的任意子类对象,实现多态
    public static void petSound(Pet pet) {
        pet.sound();
    }

    public static void main(String[] args) {
        Pet pets[] = new Pet[] {
            new Dog("大黄"),
            new Cat("花花"),
            new Dog("小黄"),
            new Cat("波斯")
        };
        int index = new Random().nextInt(pets.length);
        petSound(pets[index]);
    }
}

2, 父类作为方法返回值的情况:

问题的引入:宠物店老板要进货,需要购买狗和猫,在PetShop中定义买狗的方法getDog(),卖猫的方法getCat()。代码如下:

public class PetShop {

    //父类引用作为方法参数时,可以传入该类的任意子类对象,实现多态
    public static void petSound(Pet pet) {
        pet.sound();
    }
    
    public static Dog getDog() {
        return new Dog("大黑");
    }
    
    public static Cat getCat() {
        return new Cat("加菲");
    }

    public static void main(String[] args) {
        Pet pets[] = new Pet[] {
            new Dog("大黄"),
            new Cat("花花"),
            new Dog("小黄"),
            new Cat("波斯")
        };
        int index = new Random().nextInt(pets.length);
        petSound(pets[index]);
        Dog dog = PetShop.getDog();
        Cat cat = PetShop.getCat();
    }
}
分析:
    如果增加了宠物的种类,那么就需要在Petshop中增高进货的方法。不利于扩展。解决的办法是定义一个统一的进货方法,方法返回Pet类型,方法参数设计为进货的种类。

public class PetShop {

    //父类引用作为方法参数时,可以传入该类的任意子类对象,实现多态
    public static void petSound(Pet pet) {
        pet.sound();
    }
    //父类引用作为方法返回值时,可以返回该类的任意子类对象,实现多态
    public static Pet getPet(String breed) {
        Pet pet = null;
        switch(breed) {
        case "dog":
            pet = new Dog();
            break;
        case "cat":
            pet = new Cat();
            break;
        }
        return pet;
    }

    public static void main(String[] args) {
        Pet pets[] = new Pet[] {
            new Dog("大黄"),
            new Cat("花花"),
            new Dog("小黄"),
            new Cat("波斯")
        };
        int index = new Random().nextInt(pets.length);
        petSound(pets[index]);
        Pet pet = PetShop.getPet("dog");
        System.out.println("新进的货物是"+pet.toString());
    }
}
分析:父类引用作为方法返回值时,可以返回该类的任意子类对象,实现多态

二, 抽象

英文翻译:abstract

1, 抽象类

定义:使用abstract关键字修饰类就是抽象类.例:

public abstract class animal{

}

上例中animal被定义为抽象类.

2, 抽象方法

被abstract关键字修饰的方法就是抽象方法.例:定义一个sound抽象方法:

public abstract class animal{

    public abstract void sound();
    
}

注:抽象方法不允许有方法体,即没有{}

3, 抽象类和方法的使用规则

1) 抽象类可以包括抽象方法或普通方法.

2) 抽象类可以定义实例属性或静态属性.

3) 若一个类中定义了抽象方法,此类就是抽象类.

4) 抽象类中不一定包括抽象方法.

5) 抽象类不允许被实例化,因为抽象类是半成品.所谓半成品就是抽象类的抽象方法没有方法体.

4, 为什么使用抽象方法

解释:让子类遵守父类的规范,即子类实现父类的抽象方法.

父类中定义抽象方法,让子类继承抽象方法,父类通过抽象方法让子类遵守规范.

子类继承父类的抽象方法后,有两种处理抽象方法的方式:

1 : 将子类也变成抽象类,缺点是子类不能被实例化.

2 : 重新定义继承的抽象方法,添加方法体.此时子类就可以定义其属性.

抽象类是专门用在继承关系中的.

Java语言是单继承,只能有一个直接父类.

标签

评论

© 2021 成都云创动力科技有限公司 蜀ICP备20006351号-1