JAVA三大特性之-------多态

Java多态

    多态是同一个行为具有多个不同表现形式或形态的能力;
    多态就是同一个接口,使用不同的实例而执行不同操作,如果所示:
多态的表现形式

多态存在的三个必要条件

  • 继承
  • 子类要重写父类的方法
  • 父类引用指向子类对象

1.父类Animal

public class Animal{
    public int num = 10;
    public static int age = 20;
    public void eat(){
        System.out.println("动物吃饭");
    }
    public static void sleep(){
        System.out.println("动物在睡觉");
    }
    public void run(){
        System.out.println("动物在奔跑");
    }
}
  1. 子类cat
public class Cat extends Animal{
    public int num = 80;
    public static int age = 90;
    public String name = "tomCat";
    public void eat(){
        System.out.println("猫吃饭");
    }
    public static void sleep(){
        System.out.println("猫在睡觉");
    }
    public void catchMouse(){
        System.out.println("猫在抓老鼠");
    }
}
  1. 测试类
Animal am = new Cat();
		am.eat();
		am.sleep();
		am.run();
		//am.catchMouse();  //这里先注释掉,等会会说明
		//System.out.pritionln(am.name);  //这里先注释,等会说明
		System.out.println(am.num);
		System.out.println(am.age);

打印结果
可以看出:

  • 子类Cat重写了父类Animal的非静态成员方法am.eat();的输出结果为:猫吃饭。调用子类
  • 子类重写了父类(Animal)的静态成员方法am.sleep();的输出结果为:动物在睡觉。调用父类
  • 未被子类(Cat)重写的父类(Animal)方法am.run()输出结果为:动物在奔跑。调用父类
  • System.out.println(am.num);//输出结果为10。调用父类
  • System.out.println(am.age);//输出结果为20。调用父类
    只有非静态的成员方法,调用子类,其他的全部调用父类

多态的优点

  • 提高了代码的维护性(继承保证)
  • 提高了代码的扩展性(由多态保证)
class Animal {
    public void eat(){
        System.out.println("eat");
    }
    
    public void sleep(){
        System.out.println("sleep");
    }
}

class Dog extends Animal {
    public void eat(){
        System.out.println("狗吃肉");
    }
    
    public void sleep(){
        System.out.println("狗站着睡觉");
    }
}

class Cat extends Animal {
    public void eat() {
        System.out.println("猫吃鱼");
    }
    
    public void sleep() {
        System.out.println("猫趴着睡觉");
    }
}

class Pig extends Animal {
    public void eat() {
        System.out.println("猪吃白菜");
    }
    
    public void sleep() {
        System.out.println("猪侧着睡");
    }
}

//针对动物操作的工具类
class AnimalTool {
    private AnimalTool(){}

    /*
    //调用猫的功能
    public static void useCat(Cat c) {
        c.eat();
        c.sleep();
    }
    
    //调用狗的功能
    public static void useDog(Dog d) {
        d.eat();
        d.sleep();
    }
    
    //调用猪的功能
    public static void usePig(Pig p) {
        p.eat();
        p.sleep();
    }
    */
      //把所有的可能都归为动物类(向上转型,一劳永逸)
    public static void useAnimal(Animal a) {
        a.eat();
        a.sleep();
    }
  
}

class DuoTaiDemo2 {
    public static void main(String[] args) {
        //我喜欢猫,就养了一只
        Cat c = new Cat();
        c.eat();
        c.sleep();
        
        //我很喜欢猫,所以,又养了一只
        Cat c2 = new Cat();
        c2.eat();
        c2.sleep();
        
        //我特别喜欢猫,又养了一只
        Cat c3 = new Cat();
        c3.eat();
        c3.sleep();
        //...
        System.out.println("--------------");
        //问题来了,我养了很多只猫,每次创建对象是可以接受的
        //但是呢?调用方法,你不觉得很相似吗?仅仅是对象名不一样。
        //我们准备用方法改进
        //调用方式改进版本
        //useCat(c);
        //useCat(c2);
        //useCat(c3);
        
        //AnimalTool.useCat(c);
        //AnimalTool.useCat(c2);
        //AnimalTool.useCat(c3);
        
        AnimalTool.useAnimal(c);
        AnimalTool.useAnimal(c2);
        AnimalTool.useAnimal(c3);
        System.out.println("--------------");
        
        //我喜欢狗
        Dog d = new Dog();
        Dog d2 = new Dog();
        Dog d3 = new Dog();
        //AnimalTool.useDog(d);
        //AnimalTool.useDog(d2);
        //AnimalTool.useDog(d3);
        AnimalTool.useAnimal(d);
        AnimalTool.useAnimal(d2);
        AnimalTool.useAnimal(d3);
        System.out.println("--------------");
        
        //我喜欢宠物猪
        //定义一个猪类,它要继承自动物,提供两个方法,并且还得在工具类中添加该类方法调用
        Pig p = new Pig();
        Pig p2 = new Pig();
        Pig p3 = new Pig();
        //AnimalTool.usePig(p);
        //AnimalTool.usePig(p2);
        //AnimalTool.usePig(p3);
        AnimalTool.useAnimal(p);
        AnimalTool.useAnimal(p2);
        AnimalTool.useAnimal(p3);
        System.out.println("--------------");
        
        //我喜欢宠物狼,老虎,豹子...
        //定义对应的类,继承自动物,提供对应的方法重写,并在工具类添加方法调用
        //前面几个必须写,我是没有意见的
        //但是,工具类每次都改,麻烦不
        //我就想,你能不能不改了
        //太简单:把所有的动物都写上。问题是名字是什么呢?到底哪些需要被加入呢?
        //改用另一种解决方案,AnimalTool.useAnimal(向上转型)。
        
    }
    
    /*
    //调用猫的功能
    public static void useCat(Cat c) {
        c.eat();
        c.sleep();
    }
    
    //调用狗的功能
    public static void useDog(Dog d) {
        d.eat();
        d.sleep();
    }
    */
}

向上转型经典案例

多态的弊端

  • 不能使用子类的特有功能
    我就想使用子类的特有功能?行不?
    行。
    怎么用呢?
    A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
    B:把父类的引用强制转换为子类的引用。(向下转型)
  • 对象间的转型问题:
    向上转型:
    Fu f = new Zi();
    向下转型:
    Zi z = (Zi)f;//要求该f必须是能够转换为Zi的。(所属关系)

猜你喜欢

转载自blog.csdn.net/qq_32963927/article/details/89245257
今日推荐