Java语法之多态

Java语法之多态

多态简单来说就是:同一个接口,使用不同的实例而执行不同操作。(相同的事物,调用其相同的方法,参数也相同时,但表现的行为却不同。)比如F1 键这个动作:如果当前在 Flash 界面下弹出的就是AS3的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。

1、多态的前提和体现

  • 有继承/实现关系(继承是多态的前提,没有继承就不会有多态)
  • 有方法重写(有相同的方法)
  • 有父类引用指向子类对象
public class Animals {                     //父类
    public void eat(){
        System.out.println("动物吃东西");
    }
}

public class Cat extends Animals{          //子类,有继承关系
    @Override
    public void eat() {                    //有方法重写
        System.out.println("猫吃鱼");   
    }
}

public class AnimalsDemo {
    Animals a=new Cat();                    //有父类引用指向子类对象
}

2、多态中变量的访问特点

public class Animals {
    public int age=40;                    //父类的成员变量age
    
    public void eat(){
        System.out.println("动物吃东西");
    }
}

public class Cat extends Animals{
    public int age=20;                    //子类的成员变量age
    
    public int weight=10;
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void playGame(){
        System.out.println("猫捉迷藏");
    }
}

public class AnimalsDemo {
    public static void main(String[] args) {
        Animals a=new Cat();
        System.out.println(a.age);
        a.eat();
    }
}

image-20240122154749420

对于Animals a=new Cat();通过多态去访问成员变量的时候访问的是父类中的(左边),编译和运行都看左边;而执行成员方法的时候执行的是子类中的(右边)。

即:用父类作为参数,而真正执行方法的时候执行的是子类的方法。

3、深入理解多态

首先定义一个父类Animals,两个子类,分别为:Cat类和Dog类。

Animal类中有eat()方法,用来表示动物吃东西的动作,而在Cat类和Dog类中重写了eat()方法,表征子类的特征,分别为猫吃鱼狗吃骨头

public class Animals {
    public void eat(){
        System.out.println("动物吃东西");
    }
}

public class Cat extends Animals{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

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

为了统一化,新建一个AnimalsOperator类来集中统计各种动物对于吃东西这一动作的具体表现形式,例如:猫吃鱼、狗吃骨头等。(将目标子类对象作为方法的参数)

public class AnimalsOperator {
    public void useAnimal(Cat c){
        c.eat();
    }
    public void useAnimal(Dog d){
        d.eat();
    }
}

现定义主方法,构造了一个AnimalsOperator对象、一个Cat对象,一个Dog对象,调用useAnimal方法来执行。

public class AnimalsDemo {
    public static void main(String[] args) {
        AnimalsOperator ao=new AnimalsOperator();
        Cat c=new Cat();
        ao.useAnimal(c);

        Dog d=new Dog();
        ao.useAnimal(d);
    }
}

输出结果显而易见:

image-20240123121447631

上述代码中,只有猫和狗两种,如果再加一种动物,那么按照以上代码的逻辑,就需要在AnimalOperator中继续再增加一个方法,非常麻烦,因此可以对以上代码用多态来改进:

public class AnimalsOperator {
    public void useAnimal(Animal a){  
        //父类作为参数去接收
        a.eat();
    }
}

public class AnimalsDemo {
    public static void main(String[] args) {
        AnimalsOperator ao=new AnimalsOperator();
        Animals c=new Cat();//用父类去接收新定义的子类
        ao.useAnimal(c);//用父类去传参,但实现子类的方法
        
        Animals d=new Dog();
        ao.useAnimal(d);
    }
}

改进后,就用父类去作为参数去接收,而执行方法的时候执行的是具体子类的方法,这就相当于父类作为一个公用的接口,去向外提供,而具体实现的方法是子类的方法。

以上是多态的好处,而在这个例子中,多态存在弊端,就是对于子类特有的方法无法实现。

4、多态中的转型

多态有一个弊端就是不能使用子类特有的功能,而转型就可以实现这一目标,从而使用子类特有的功能。

public class Cat extends Animals{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void plagGame(){
        System.out.println("猫捉迷藏");
    }
}

public class Animals {
    public void eat(){
        System.out.println("动物吃东西");
    }
}

(1)向上转型

从子到父——>把子类对象赋值给父类对象——>向上转型。

public class AnimalsDemo {
    public static void main(String[] args) {
        Animals a=new Cat();  //把子类对象赋值给父类对象————>向上转型
        a.eat();
    }
}

image-20240123132514644

在该例子中,虽然可以输出"猫吃鱼",但是由于父类无法实现子类的特有功能,所以无法实现”猫捉迷藏“的方法,因此需要向下转型。

(2)向下转型

从父到子——>把父类对象强制转换为子类对象——>向下转型

public class AnimalsDemo {
    public static void main(String[] args) {
        Animals a=new Cat(); 
        Cat c=(Cat)a;   //把父类对象强制转换为子类对象————>向下转型
        c.plagGame();   //实现子类特有的方法
    }
}

image-20240123132544197

posted @ 2024-01-25 17:06  6小1  阅读(4)  评论(0编辑  收藏  举报