多态01(面向对象编程三大特征之一)

本文介绍了面向对象编程中的多态概念,包括方法多态和对象多态,以及如何在Java中实现和应用多态,如向上转型、向下转型和处理属性重写。通过实例演示了如何解决主人喂食问题,提升代码复用性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、引入

请编写一个程序,Master主人类中有一个feed(喂食)方法,可以完成主人给动物喂食物的信息。不同动物吃不同食物
Food(父类):Fish Bone Rice
Animals(父类):Cat Dog Pig
传统方法解决:

package poly_;

public class Poly01 {
    public static void main(String[] args) {
        Master tom = new Master("Tom");
        Dog dog = new Dog("大黄");
        Bone bone = new Bone("大棒骨");

        tom.feed(dog, bone);
        System.out.println("==============");
        Cat cat = new Cat("花猫");
        Fish fish = new Fish("黄花鱼");
        tom.feed(cat, fish);
    }
}
//食物类
class Food {
    private String name;

    public Food(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

class Fish extends Food {
    public Fish(String name) {
        super(name);
    }
}

class Bone extends Food {
    public Bone(String name) {
        super(name);
    }
}
//动物类
class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }
}
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }
}
//主人类
class Master {
    private String name;

    public Master(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void feed(Dog dog, Bone bone) {
        //主人给狗喂骨头
        System.out.println("主人"+this.name+"给"+dog.getName()+"吃"+bone.getName());
    }

    public void feed(Cat cat, Fish fish) {
        //主人给猫喂鱼
        System.out.println("主人"+this.name+"给"+cat.getName()+"吃"+fish.getName());
    }
}

在这里插入图片描述

如果动物增加,食物增加
Pig–>Rice
Tiger–>Meat
===> feed方法很多,不利于管理和维护

问题是:代码的复用性不高,而且不利于代码维护
解决方案:引出我们要讲解的多态

二、多态介绍

多[多种]态[状态]基本介绍 :方法或对象具有多种形态。
多态是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

1、方法的多态

重写和重载体现多态。

2、对象的多态

编译:javac,运行:java

(1) 一个对象的编译类型和运行类型可以不一致

Animal animal = new Dog();
父类的引用指向子类的对象。
父类Animal 的引用animal 指向子类Dog 的对象。

(2) 编译类型在定义对象时,就确定了,不能改变
Animal animal = new Dog(); 【animal编译类型是Animal,运行类型Dog】
animal = new Cat(); 【animal的运行类型变成了Cat,编译类型仍然是Animal】

(3) 运行类型是可以变化的

(4) 编译类型看定义时 = 号的左边,运行类型看 = 号的右边

  • 示例
	//体验对象多态特点
	public class Poly02_objpoly {
	    public static void main(String[] args) {
	        // animal的编译类型在定义对象时,就确定了-> 是 = 号的左边的Animal类
	
	        Animal animal = new Dog();//animal编译类型是Animal,运行类型Dog
	        animal.cry();//因为运行时,即 执行到该行时,animal运行类型是Dog
	        System.out.println("======================");
	        
	        animal = new Cat();//animal编译类型是Animal,运行类型Cat
	        animal.cry();
	    }
	}
	
	class Animal {
	    public void cry() {
	        System.out.println("动物喊叫");
	    }
	}
	class Cat extends Animal {
	    public void cry() {
	        System.out.println("喵喵喵");
	    }
	}
	class Dog extends Animal {
	    public void cry() {
	        System.out.println("汪汪汪");
	    }
	}

在这里插入图片描述

  • 解决前文的主人喂食问题
    //使用多态机制,可以统一的管理主人喂食的问题
    public void feed(Animal animal, Food food) {
        System.out.println("主人"+this.name
        				+"给"+animal.getName()+"吃"+food.getName());
    }

animal 的编译类型是Animal,可以指向(接受)Animal 子类的对象。
food 的编译类型是Food,可以指向(接受)Food子类的对象。

三、注意事项&细节

1、多态的前提

多态的前提是两个对象(类)存在继承关系。

2、多态的向上转型

  1. 本质:父类的引用指向了子类的对象
  2. 语法:父类类型引用名 = new子类类型()
    Animal animal = new Cat();
    Object obj = new Cat();//可以吗? 可以 Object 也是 Cat 的父类
  3. 特点:编译类型看左边,运行类型看右边
  4. 向上转型调用方法的规则如下:
    (1) 可以调用父类中的所有成员(需遵守访问权限)
    (2) 但是不能调用子类的特有的成员
    (#)因为在编译阶段,能调用哪些成员,是由编译类型来决定的
    (3) 最终运行效果看子类(运行类型)的具体实现,即调用方法时,按照从子类(运行类型)开始查找方法,然后调用,规则我前面我们讲的方法调用规则一致。
  • 示例
	 Animal animal = new Cat();
	 animal.eat();

先在Cat中寻找有没有eat方法,如果没有,就找Cat类的父类->>

	Animal animal = new Cat();
	animal.catchMouse();错误

如果父类 animal 类中没有catchMouse(); 只有子类Cat类中有。那么animal.catchMouse();语句是错误的。
不能调用子类的特有的成员。

3、多态的向下转型

接上文,如果animal非要访问catchMouse方法怎么办。

  1. 语法:子类类型引用名 = (子类类型)父类引用
  2. 只能强转父类的引用,不能强转父类的对象
    对象是在堆中new出来的,开辟了空间、分配了地址,是无法强制转换的。
    引用是在栈中的,存放了堆中对象的地址,是可以修改引用的指向的。
  3. 要求父类的引用必须指向的是当前目标类型的对象
  4. 当向下转型后,就可以调用子类类型中所有的成员
  • 举例
	Animal animal = new Cat();
	
    Cat cat = (Cat) animal;
    cat.catchMouse();

cat的编译类型是Cat,运行类型是Cat
解释《要求父类的引用必须指向的是当前目标类型的对象》

4、属性重写问题

属性没有重写之说!属性的值看【编译】类型 。

  • 举例

Base sub = new Sub();
sub.count 是什么?

public class PolyDetails02 {
    public static void main(String[] args) {
        Base sub = new Sub();
        System.out.println(sub.count);
    }
}

class Base {
    int count = 10;
}
class Sub extends Base {
    int count = 20;
}

在这里插入图片描述

instanceOf 比较操作符

instanceOf 比较操作符,用于判断对象运行类型是否为XX类型 或 XX类型的子类型。

(1)对象bb是BB类型?或是BB类型的子类吗?

public class PolyDetails03 {
    public static void main(String[] args) {
        BB bb = new BB();
        System.out.println(bb instanceof BB);
    }
}

class AA {}
class BB extends AA {}

:true
(2)对象bb是AA类型?或是AA类型的子类吗?

System.out.println(bb instanceof AA);

:true

(3)编译类型还是运行类型

AA aa = new BB()

aa编译类型AA,aa运行类型是BB

System.out.println(aa instanceof AA);
System.out.println(aa instanceof BB);

:true
:true

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值