多态的使用及注意事项

2023-01-19 14:09:55

多态:字面意思讲,就是某一类事物的多种形态。简单来说,就是一个对象对应着多个类型
1.多态在代码中的体现:

父类或者接口的引用指向了其子类对象。

2.多态的好处:

1.提高了代码的扩展性,前期定义的代码可以使用后期的内容。

//先定义Cat类型继承Animal类,后期定义Dog类,同样使用先前定义好的method方法
public class Duotai{
    public static void main(String[]args){
        Animal c = new Cat();
        Animal d = new Dog();
        method(c);
        method(d);
    }
    public static void method(Animal a){
    a.eat();
}
//定义Animal抽象类
abstract class Animal{
    abstract void eat();
}
//创建Dog类继承Animal抽象类并实现其中的方法
class Dog extends Animal{
    void eat(){
        System.out.println("啃骨头");
    }
    void lookHome(){
        System.out.println("看家");
    }
}
//创建Cat类继承Animal抽象类并实现其中的方法
class Cat extends Animal{
    void eat(){
        System.out.println("吃鱼");
    }
    void catchMouse(){
        System.out.println("抓老鼠");
    }
}

运行结果如下:
Compiling Duotai.java……
——Output——
吃鱼
啃骨头
[Finished in 0.6s]

2.多态的弊端:

前期定义的内容不能使用后期子类的特有内容,因为在Animal c = new Cat()的时候,Cat对象提升为了动物类型,所以特有的方法无法访问。

public class Duotai{
    public static void main(String[]args){
        Animal c = new Cat();
        Animal d = new Dog();
        c.catchMouse();
        d.lookHome();
    }
}
//定义Animal接口
abstract class Animal{
    abstract void eat();
}
//创建Dog类继承Animal抽象类并实现其中的方法
class Dog extends Animal{
    void eat(){
        System.out.println("啃骨头");
    }
    void lookHome(){
        System.out.println("看家");
    }
}
//创建Cat类继承Animal抽象类并实现其中的方法
class Cat extends Animal{
    void eat(){
        System.out.println("吃鱼");
    }
    void catchMouse(){
        System.out.println("抓老鼠");
    }
}

结果如下:两个子类对象因向上转型而无法访问其特有方法
Compiling Duotai.java……
Duotai.java:228: 错误: 找不到符号
c.catchMouse();
^
符号: 方法 catchMouse()
位置: 类型为Animal的变量 c
Duotai.java:229: 错误: 找不到符号
d.lookHome();
^
符号: 方法 lookHome()
位置: 类型为Animal的变量 d
2 个错误
[Finished in 0.6s]

解决弊端问题:

所以要想使用子类中特有的功能的时候,可以对对象进行向下转型,就可以使用子类中的特有方法。

public class Duotai{
    public static void main(String[]args){
        Animal c = new Cat();
        Cat a = (Cat)c;
        a.eat();
        a.catchMouse();
        Animal d = new Dog();
        Dog b = (Dog)d;
        b.eat();
        b.lookHome();
    }
}
//定义Animal接口
abstract class Animal{
    abstract void eat();
}
//创建Dog类继承Animal抽象类并实现其中的方法
class Dog extends Animal{
    void eat(){
        System.out.println("啃骨头");
    }
    void lookHome(){
        System.out.println("看家");
    }
}
//创建Cat类继承Animal抽象类并实现其中的方法
class Cat extends Animal{
    void eat(){
        System.out.println("吃鱼");
    }
    void catchMouse(){
        System.out.println("抓老鼠");
    }
}

结果如下:
Compiling Duotai.java……
——Output——
吃鱼
抓老鼠
啃骨头
看家
[Finished in 0.6s]

3.注意:

对于转型,自始至终都是子类对象在做着类型的变化。在转型前,一般用instanceof进行类型的判断,以增强代码的健壮性。

4.多态时成员的特点

1.成员变量:
编译时:参考引用型变量所属的类中是否有调用的成员变量,有,编译通过,没有,编译失败。

public class DuotaiDemo{
    public static void main(String [] args){
        Fu f = new Zi();//向上转型成为了Fu类
        System.out.println(f.num);//调用了Fu类中没有的成员变量,编译失败
    }
}

class Fu{
}

class Zi extends Fu{
    int num=3;
}

结果如下:
Compiling DuotaiDemo.java……
DuotaiDemo.java:6: 错误: 找不到符号
System.out.println(f.num);
^
符号: 变量 num
位置: 类型为Fu的变量 f
1 个错误
[Finished in 0.5s]

2.运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。

public class DuotaiDemo{
    public static void main(String [] args){
        Fu f = new Zi();
        System.out.println(f.num);
    }
}

class Fu{
    int num=5;
}

class Zi extends Fu{
    int num=3;

}

结果如下:可以看出来结果是向上转型后的类的结果
Compiling DuotaiDemo.java……
——Output——
5
[Finished in 0.6s]

简单来说:在对于多态中的成员变量时,编译和运行都参考等号的左边。

2.成员方法(非静态)
编译时:参考引用型变量所属的类中是否有调用的方法,有,编译通过,没有,编译失败。

public class DuotaiDemo{
    public static void main(String [] args){
        Fu f = new Zi();//在此处对象向上转型成了Fu类型对象
        f.show();//Fu类型中没有show()方法,编译失败;
    }
}

class Fu{

}

class Zi extends Fu{
    void show(){
        System.out.println("zi show");
    }
}

运行时:参考对象所属的类中是否有调用的方法,子类方法会覆盖父类的方法
Compiling DuotaiDemo.java……
——Output——
zi show
[Finished in 1.0s]

public class DuotaiDemo{
    public static void main(String [] args){
        Fu f = new Zi();
        f.show();
    }
}

class Fu{
    void show(){
        System.out.println("fu show");
    }
}

class Zi extends Fu{
    void show(){
        System.out.println("zi show");
    }
}

结果如下

简单说:编译看左边,运行看右边

3.静态方法
编译时:参考对象所属类中是否有调用的静态方法
运行时:参考对象所属类中是否有调用的静态方法
简单说:编译和运行都看左边
其实对于静态方法,是不需要对象的,直接用类名调用

public class DuotaiDemo{
public static void main(String [] args){
Fu f = new Zi();
f.show();
f.method();
}
}

class Fu{
void show(){
System.out.println(“fu show”);
}
static void method(){
System.out.println(“Fu static method”);
}
}

class Zi extends Fu{
void show(){
System.out.println(“zi show”);
}
static void method(){
System.out.println(“zi static method”);
}
}

结果如下:当方法是静态的时,输出的是对象所属类的静态方法
当方法不是静态时,输出的是引用型变量所属类中的方法
Compiling DuotaiDemo.java……
——Output——
zi show
Fu static method
[Finished in 0.6s]

  • 作者:ILYPTING
  • 原文链接:https://blog.csdn.net/ILYPTING/article/details/70833202
    更新时间:2023-01-19 14:09:55