欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点

程序员文章站 2022-05-25 20:41:57
...

对象的多态

例子:

class 动物
{}
classextends 动物
{}
classextends 动物
{}

猫 x = new();
动物 x = new(); 

一般一个对象两种形态,我们就可以认为是多态了
例如:动物 x = new 猫();

 猫这类事物即具备猫的形态,又具备着动物的形态.
    这就是对象多态性

简单说:就是一个对象对应着不同类型

左边是动物,右边是猫,两种形态,我们就可以说它是多态的

多态在代码的体现:

		父类或者接口的引用指向其子类的对象
多态的好处:
      提高了代码的扩展性.前期定义的代码可以使用后期的内容

多态的弊端:
      前期定义的内容不能使用(调用)后期子类的特有内容.

多态的前提:
      1.必须有关系,继承,实现
      2.要有覆盖

例子:

abstract class Animal
{
    abstract void egt();    //吃东西
}

class Dog extends Animal
{
    void egt()
    {
        System.out.println("啃骨头");
    }
    void lookHome()
    {
        System.out.println("看家");
    }
}

class Cat extends Animal
{
    void egt()
    {
        System.out.println("吃鱼");
    }
    void catchMouse()
    {
        System.out.println("抓老鼠");
    }
}

public class DuoTaiDemo {
    public static void main(String[] args){

        Animal a = new Cat(); 
        //自动类型提升,猫对象提升了动物类型.但是特有功能无法访问.
                              //作用就是限制对特有功能的访问.
                              //专业讲:向上转型.
        a.egt();
         //c.catchMouse();//报错
		 method(a);//这样可以提高代码的复用性,如果继续new别的对象的时候,也能用
       
        
        //如果还想用具体动物猫的特有功能.
        //你可以讲该对象进行向下转型.
        Cat c = (Cat)a;//向下转型是为了使用子类中的特有方法.
        c.egt();
        method(c);//这样可以提高代码的复用性,如果继续new别的对象的时候,也能用
        c.catchMouse();//猫的特有功能(方法)

        //注意: 对于转型, 自始至终都是子类对象在做类型的变化.
        //Animal a1 = new Dog();  
        //Cat c1 = (Cat)a1;
        //报错: ClassCastException 类型转换异常
        //这里是Dog类型向上转型,然后把它向下转型为Cat...
    }
    public static void method(Animal a) //Animal a = new 不同子类对象()
    {
        a.egt();
    }
}

.
.
.

多态类型判断

关键字: instanceof

例子:

 public static void method(Animal a) //Animal a = new 不同子类对象()
    {
        a.egt();
        if(a instanceof Cat)   
        {                       
            Cat b = (Cat)a;
            b.catchMouse();
        }
        else if(a instanceof Dog)
        {
            Dog b = (Dog)a;
            b.lookHome();
        }
        //这样挨个判断的几乎没有...
    }

关键字instanceof:

		用于判断对象的具体类型.只能用于引用数据类型判断
		通常在向下转型前用于健壮性的判断.

一般在我们转型的时候判断,让它给我们反馈.
.
.
.

多态成员的特点

1.成员变量

例子:

class Fu
{
    int num = 3;
}

class Zi extends Fu
{
    int num = 4;
}

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

结果:
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
因为Zi类,向上转型为Fi类
所有f.num就是调用父类的num
不过一般开发不这样弄,因为都已经有了,直接调用就完事了…
面试可能会问到

.
.
.

2.成员函数

例子:

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

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

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

结果:
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
为什么会输出zi show

图解:JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
刚开始主函数main进栈
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
然后f new Zi()
Zi类继承了Fu类,他们两个一起进入了方法区
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
接着创建了一个对象,并分配了地址
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
再然后把地址给到变量f, f指向对象在堆内存的地址
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
接着f调用了show()方法
这时就会先在Zi类show()方法,发现有,就输出了—zi show
假设Zi类没有show()方法,那么就是通过super进入Fu里面找show()方法

Fu还没有的话,就直接报错了
.
.
.

3.静态函数

例子:

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

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

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

结果:
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
为什么会输出:zi static method
图解:
刚开始与前面差不多
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
不同的是这里的静态方法是加载进静态的方法区
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
JAVA中面向对象-对象的多态 与 多态类型判断 以及 多态成员的特点
全部好了之后执行下面的语句调用了静态方法f.method();
这时因为Zi类向上转型,于是变成了Fu类的.
于是就调用了Fu类的静态方法了,输出:fu static metheod

如果是 Zi f = new Zi();
那么执行静态方法f.method();的时候,就输出:zi static metheod

其实如果我们调用静态方法时,不需要用到对象时,可以直接通过类进行调用进行了
例如:

Fu.method();
Zi.method();

.
.
.
通过上面三个例子我们可以得出多态成员的特点

1.成员变量
        编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败.
        运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量.
        简单说:编译和运行都参考等号的左边.
        作为了解就行了

    2.成员函数(非静态)
        编译时:参考引用型变量所属的类中的是否有调用的成员函数.有,编译通过, 没有, 编译失败.
        运行时:参考的是对象所属的类中是否有调用的函数.
        简单说:编译看左边,运行看右边

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