面向对象6(多态(重要))

多态:

Java中概念:父类类型引用指向子类对象。
概述:事物的多种状态。

  • 对象的多态:同一个对象,有不同的名称和描述。
  • 类的多态:同一个类,可以在不同场景下有不同的表现。

多态的前提:

  1. 要有子父类的继承(实现)关系。
  2. 有方法的重写。
  3. 父类的引用指向子类的对象。

(熟知)多态中成员方法的访问特点:

  • 编译看左边,运行看右边。
  • 编译的时候,要看【 = 】左边的引用所属的类型中,是否有该方法的定义,没有就编译失败。
  • 运行的时候,要看【 = 】右边的引用所属的类型中,是如何实现该方法的。最终运行的右边子类里该方法的重写结果。

多态中的类型转换:

一,向上类型转换:子类转换成父类(由小转大)

  • 语法:(直接赋值)父类 对象名 = new 子类()
class Pet{
    String name;

    public Pet(String name) {
        this.name = name;
    }
    public void eat(){
        //各种宠物进食不一样,不能定义
        //暂时不用abstract修饰,空方法体
    }
}
class Dog extends Pet{

    public Dog(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println( name + "吃骨头");
    }
}
class Cat extends Pet{

    public Cat(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println( name + "吃鱼");
    }
}
class Master{
    public void feed(Pet pet){//参数是父类,调用子类在父类中继承的方法
        pet.eat();
    }
}
public class Demo {

    public static void main(String[] args) {
    	//需求:主人饲养宠物
    	Master master = new Master();
        Dog dog = new Dog("狗狗");
        Cat cat = new Cat("猫猫");        
        master.feed(dog);//实际参数是子类
        master.feed(cat);//实际参数是子类

		Pet pet = new Dog("小狗");
        pet.eat();
    }
}

输出结果:
在这里插入图片描述

结论:
语法:

  1. 可以直接赋值 父类 对象名 = new 子类(),再调用子类继承父类中的方法,父类对象名.方法名(),输出的是子类方法重写的结果。
  2. 可以把父类作为其他类中方法的参数,再调用父类中被继承的方法,实例化对象,再调用方法 对象名.方法名(子类实例对象)

作用:

  1. 增强类的选择范围(可以访问任一继承父类的子类)
  2. 降低类的能力(只能访问在父类中继承的方法,无法访问自身特有的方法)

二,向下类型转换:父类转子类(由大转小)

  • 语法:子类类型 引用名称 = (子类类型)父类类型的引用
class Pet{
    String name;

    public Pet(String name) {
        this.name = name;
    }
    public void eat(){
        //各种宠物进食不一样,不能定义
        //暂时不用abstract修饰,空方法体
    }
}
class Dog extends Pet{

    public Dog(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println( name + "吃骨头");
    }
    public void play(){
        System.out.println("玩飞盘");
    }
}
class Cat extends Pet{

    public Cat(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println( name + "吃鱼");
    }
    public void play(){
        System.out.println("玩毛球");
    }
}
class Master{
    public void feed(Pet pet){//参数是父类
        pet.eat();
    }
    public void play(Pet pet){
    	//instanceof关键字,判断左边的引用是否为右边类型,返回布尔值
        if (pet instanceof Dog){
            ((Dog) pet).play();//向下转换
        }
    }
}
public class Demo {

    public static void main(String[] args) {
        Master master = new Master();
        Dog dog = new Dog("狗狗");
        Cat cat = new Cat("猫猫");
        master.play(dog);//玩飞盘

        //Pet pet = new Dog("小狗");
        //pet.play();报错,向上转换只能调用继承的方法
    }
}

作用:子类类型恢复原本就有的访问范围,可以访问自身特有的方法。

class Master{
    public void feed(Pet pet){//参数是父类
        pet.eat();
    }
    public void play(Pet pet){
        if (pet instanceof Dog){//判断左边的引用是否为右边类型,返回布尔值
            ((Dog) pet).play();//向下转换
        }
    }
}

Master类中的play方法,父类Pet每增加一个子类,里面就要增加一个判断,多次修改代码对以后编程不利。
解决方法:工厂模式(暂没学)

多态中的属性:

  • 不同名:
class Fu{
    int x = 200;

}
class Zi extends  Fu{
    int y = 100;

}
public class Demo {

    public static void main(String[] args) {
        Fu fu = new Zi();
        System.out.println(fu.x);//200
//      System.out.println(fu.y);报错
    }
}
  • 同名:
class Fu{
    int x = 200;

}
class Zi extends  Fu{
    int x = 100;

}
public class Demo {

    public static void main(String[] args) {
        Fu fu = new Zi();
        System.out.println(fu.x);// 200
    }
}

结论:

  • 1、多态中访问不同名属性,编译时看表达式的左边
  • 2、多态中访问同名属性,运行时看表达式的左边

多态中的方法:

  • 不同名:
class Fu{
    public void method(){
        System.out.println("Fu类中的method方法.....");
    }

}
class Zi extends  Fu{
    public void function(){
        System.out.println("Zi类中的function方法.....");
    }

}
public class Demo {

    public static void main(String[] args) {
        Fu fu = new Zi();
        fu.method();//Fu类中的method方法.....
        //fu.function();报错
    }
}
  • 同名:
class Fu{
    public void method(){
        System.out.println("Fu类中的method方法.....");
    }

}
class Zi extends  Fu{
    public void method(){
        System.out.println("Zi类中的method方法.....");
    }

}
public class Demo {

    public static void main(String[] args) {
        Fu fu = new Zi();
        fu.method();//Zi类中的method方法.....
    }
}
  • static同名方法:
class Fu{
    public static void method(){
        System.out.println("Fu类中的method方法.....");
    }

}
class Zi extends  Fu{
    public static void method(){
        System.out.println("Zi类中的method方法.....");
    }

}
public class Demo {

    public static void main(String[] args) {
        Fu fu = new Zi();
        fu.method();//Fu类中的method方法.....
    }
}

结论:
1、多态中不同名方法,编译时看表达式的左边
2、多态中同名方法,运行时看表达式的右边
3、多态中同名静态方法,运行时看表达式的左边

多态的内存图解
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值