DUFQ_2020.12.10-杜飞强-抽象类

知识巩固

Object是所有类的父类,是最高类,java语言是单继承的,一个类只能有一个直接父类。

方法重写:override

​ 规则1:方法名称相同

​ 规则2:参数相同

​ 规则3:返回值相同

​ 规则4:返回修饰符不能小于父类的,即private<默认修饰符<protected<public

方法重载:overload

​ 规则1:方法名称相同

​ 规则2:参数不同

​ 规则3:返回值无关

多态

​ 规则1:多态一定继承在关系中

​ 规则2:多态一定在方法中重写

​ 规则3:多态一定在父类指向子类的实例中

多态中的多值得是子类数量的多少

向上转型

​ 里氏替换原则:派生类(子类)对象可以在程式中代替其基类(超类)对象。

​ 子类的功能比父类多

​ 父类引用指向子类对象,或者说子类转换为父类类型。eg:pet = dog;

向下转型

​ 子类引用指向父类对象,或者说父类转换我子类类型。eg:dog = (Dog)pet;

多态中父类调用子类的方法规则

​ 父类能调用自己从父类继承的方法,即使方法被子类重写也能调用。

​ 父类不能调用子类新增加的属性或方法

类与类之间的三种关系

​ is a 继承 A类是B类的一种, B类是通用类, A类是特殊类, 也只有当两个类符合is a 关系时才可以使用继承

​ use a 使用

​ has a 包含

多态的使用

父类引用作为方法参数的情况
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作为方法参数

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(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]);
    }
}

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

引入问题:宠物店老板要进货,需要购买狗和猫,在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修饰的类称为抽象类

public abstract class Pet {

}

抽象方法

使用abstract修饰的方法称为抽象方法

public abstract class Pet {
    public abstract void sound() ;
}

PS:抽象方法不允许有方法体,即不能含有{}

抽象类和抽象方法的规则

​ 规则1:抽象类可以包含普通方法或抽象方法

​ 规则2:抽象类可以定义实例属性或静态属性

​ 规则3:如果一个类中可以包含抽象方法,那么这个类必须是抽象类

​ 规则4:抽象类中不一定包含抽象方法

​ 规则5:抽象类不允许实例化

为什么使用抽象类

​ 抽象类在OOP的思想中,是专门用在继承关系中的,抽象类在继承关系中当做父类,让子类继承抽象类。

​ 当子类继承抽象类后,子类也继承了父类的抽象方法,此时子类有两种处理抽象方法的办法,第一种将子类定义为抽象类,但是这种处理方法会导致子类不能被实例化。第二种处理方法是将子类实现父类的抽象方法,实现抽象方法就是在子类中将抽象方法在定义一遍并且添加方法体。此时子类就没有抽象方法,子类就不是抽象方法,因此可以实例化子类对象。

​ 为什么使用抽象类?

​ 抽象类中定义抽象方法,让子类继承抽象方法,父类通过抽象方法让子类遵守父类的规范,这里的规范是指父类的抽象方法,遵守规范是指子类实现父类的抽象方法。

标签

评论

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