06-java面向对象:多态、实例初始化

目录

6.3 多态(Polymorphism)

6.3.1 多态解决什么样的问题

6.3.2 多态的形式和体现

1、多态引用

2、多态引用的表现

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

4、多态演示

6.3.3 应用多态解决问题

1、声明变量是父类类型,变量赋值子类对象

2、数组元素是父类类型,元素对象是子类对象

3、方法返回值类型声明为父类类型,实际返回的是子类对象

6.3.4 向上转型与向下转型

1、为什么要类型转换呢?

2、如何向上转型与向下转型

3、instanceof关键字

6.3.5 虚方法

6.3.6 成员变量没有多态一说

6.4 实例初始化

6.4.1 构造器

1、构造器的作用

2、构造器的语法格式

3、同一个类中的构造器互相调用

4、继承时构造器如何处理

5、IDEA生成构造器:Alt + Insert

6、IDEA查看构造器和方法形参列表快捷键:Ctrl + P

6.4.2 非静态代码块(了解)

1、非静态代码块的作用

2、非静态代码块的意义

3、非静态代码块的执行特点

4、非静态代码块的语法格式

5、非静态代码块的应用

6.4.3 实例初始化过程(了解)

1、实例初始化的目的

2、实例初始化相关代码

3、实例初始化方法

4、实例初始化执行特点


6.3 多态(Polymorphism)

多态是继封装、继承之后,面向对象的第三大特性。它表示一个对象具有多重特征,可以在特定的情况下表现出不同的状态。

6.3.1 多态解决什么样的问题

有的时候,我们在设计一个数组、或一个成员变量、或一个方法的形参、返回值类型时,无法确定它具体的类型,只能确定它是某个系列的类型。

案例:

(1)声明一个Dog类,包含public void eat()方法,输出“狗狗啃骨头”

(2)声明一个Cat类,包含public void eat()方法,输出“猫咪吃鱼仔”

(3)声明一个Person类,

  • 包含宠物属性

  • 包含领养宠物方法 public void adopt(宠物类型 pet)

  • 包含喂宠物吃东西的方法 public void feed(),实现为调用宠物对象.eat()方法

    问题: 1、从养狗切换到养猫怎么办? 修改代码把Dog修改为养猫? 2、或者有的人养狗,有的人养猫怎么办? 3、要是同时养多个狗,或猫怎么办? 4、要是还有更多其他宠物类型怎么办?


public class Dog {
    public void eat(){
        System.out.println("狗狗啃骨头");
    }
}


public class Cat {
    public void eat(){
        System.out.println("猫咪吃鱼仔");
    }
}


public class Person {
    private Dog dog;

    //adopt:领养
    public void adopt(Dog dog){
        this.dog = dog;
    }

    //feed:喂食
    public void feed(){
        if(dog != null){
            dog.eat();
        }
    }
    /*
    问题:
    1、从养狗切换到养猫怎么办?   
    	修改代码把Dog修改为养猫?
    2、或者有的人养狗,有的人养猫怎么办?  
    3、要是同时养多个狗,或猫怎么办?
    4、要是还有更多其他宠物类型怎么办?
    如果Java不支持多态,那么上面的问题将会非常麻烦,代码维护起来很难,扩展性很差。
    */
}

6.3.2 多态的形式和体现

1、多态引用

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

父类类型:指子类继承的父类类型。

所以说继承是多态的前提

2、多态引用的表现

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

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

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

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

4、多态演示

让Dog和Cat都继承Pet宠物类。



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 + "吃东西");
    }
}



public class Cat extends Pet {
    //子类重写父类的方法
    @Override
    public void eat() {
        System.out.println("猫咪" + getNickname() + "吃鱼仔");
    }

    //子类扩展的方法
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}


public class Dog extends Pet {
    //子类重写父类的方法
    @Override
    public void eat() {
        System.out.println("狗狗" + getNickname() + "啃骨头");
    }

    //子类扩展的方法
    public void watchHouse() {
        System.out.println("看家");
    }
}


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重写的方法
    }
}

6.3.3 应用多态解决问题

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

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

public class OnePersonOnePet {
    private Pet pet;
    public void adopt(Pet pet) {//形参是父类类型,实参是子类对象
        this.pet = pet;
    }
    public void feed(){
        pet.eat();//pet实际引用的对象类型不同,执行的eat方法也不同
    }
}

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、数组元素是父类类型,元素对象是子类对象
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方法也不同
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值