多态

1、什么是多态函数

“多态”是JAVA的一种重要特性,能够理解为事物存在的多种形态。优化

不过,这只是字面上来理解,等于废话。那么究竟何为多种形态呢,接下来,举一个现实生活中的例子。spa

好比,动物里有猫和狗。猫摆在面前,你可说它是猫,也能够说它是动物。code

说它是猫时,用JAVA语句表示即   猫 x=new 猫;对象

说它是动物时,用JAVA语句表示即  动物 x=new 猫;blog

这样,实体x即具有猫的类型,也具有动物类型。但必须一个前提,即“猫”必须是“动物”中的一种,若是“狗 x=new 猫”就不对了。继承

经过以上的例子,咱们能够看出,实体除了具有本类类型,还能够具有其它类型。这种是“多态”。编译

 

先看如下代码,这是使用非多态方式编写class

代码以下:变量

package com.duotai;

public class DuoTaiDemo {

    public static void main(String[] args) {

        myFun(new Cat());
        myFun(new Dog());
        myFun(new Pig());
    }

    // 动物“吃”的功能提取出来封装成函数
    public static void myFun(Cat c) {
        c.eat();
    }

    public static void myFun(Dog d) {
        d.eat();
    }

    public static void myFun(Pig p) {
        p.eat();
    }

}

// 如下定义抽象类,定义了动物有“吃”的功能
abstract class Animal {
    abstract void eat(); // 动物吃什么不知道,定义成抽象。定义体系中的基本功能。只要继承了这个类,必有此功能。
}

// 以定义具体类,复写动物的吃的功能,并有本身独特的功能
class Cat extends Animal {
    public void eat() { // 复写Animal类的eat方法
        System.out.println("猫吃鱼");
    }

    public void catchMouse() { // 本身特有的方法
        System.out.println("猫抓老鼠");

    }
}

class Dog extends Animal {
    public void eat() { // 复写Animal类的eat方法
        System.out.println("狗吃骨头");
    }

    public void kanJia() { // 本身特有的方法
        System.out.println("看家");
    }
}

class Pig extends Animal {
    public void eat() { // 复写Animal类的eat方法
        System.out.println("猪吃饲料");
    }

    public void gongDi() { // 本身特有的方法
        System.out.println("拱地");
    }
}

 

以上代码,定义了一个“动物”类,其有一个“吃”的功能,可是因为每种动物吃的方式都不同,因此定义成抽象类。之后让具体的动物去复写。

而后,定义了三个继承类,“猫”“狗”“猪”,复写了动物的“吃”的功能。

主函数调用时,要创建子类对的引用对象,再调用吃的方式。

这样编写时,会有一个弊端,那就是继承的子类若是增长时,则要修改主函数中的“吃”的代码。子类越多,这端代码就越长,扩展性比较弱。

如何优化呢?

子类“猫”,继承了“动物”类,是动物中的一种,那就能够用“动物”的引用来指向子类实例,即Aniaml c=new cat,c.eat(),运行结果是子类的,由于父类中有,子类中也有,就运行子类的eat(),由于子类复写了。这就是一个事物具有多种形态。

代码简化以下:

package com.duotai;

public class DuoTaiDemo {

    public static void main(String[] args) {

        myFun(new Cat());
        myFun(new Dog());
        myFun(new Pig());
    }

    // 动物“吃”的功能提取出来封装成函数
    public static void myFun(Animal a){        //只要定义Animal便可。至关于Animal a=new Cat();
        a.eat();
    }

}

// 如下定义抽象类,定义了动物有“吃”的功能
abstract class Animal {
    abstract void eat(); // 动物吃什么不知道,定义成抽象。定义体系中的基本功能。只要继承了这个类,必有此功能。
}

// 以定义具体类,复写动物的吃的功能,并有本身独特的功能
class Cat extends Animal {
    public void eat() { // 复写Animal类的eat方法
        System.out.println("猫吃鱼");
    }

    public void catchMouse() { // 本身特有的方法
        System.out.println("猫抓老鼠");

    }
}

class Dog extends Animal {
    public void eat() { // 复写Animal类的eat方法
        System.out.println("狗吃骨头");
    }

    public void kanJia() { // 本身特有的方法
        System.out.println("看家");
    }
}

class Pig extends Animal {
    public void eat() { // 复写Animal类的eat方法
        System.out.println("猪吃饲料");
    }

    public void gongDi() { // 本身特有的方法
        System.out.println("拱地");
    }
}

 

2、多态的代码提现形式

  父类的引用引向本身的子类对象。

  父类的引用也能够接收本身的子类对象。如以上代码中:Animal a=new Cat()

 

3、多态的做用

  提升了程序的扩展性

 

4、多态的前提

  类与类有关系,必须是继承或是实现。如以上代码中,Cat、Dog、Pig类都继承了Animal类

  一般还有一个前提,就是“复写”。如以上代码中,子父类中都有eat()方法,子类复写父类。

 

5、多态的弊端

  提升了扩展性,可是只能是父类的引用访问父类中的成员

 

6、多类中数据的转型

  在基本数据类型中,存在着数据类型提高现象,如double=2.3+1,会将1由int提高为double

  在多类中,引用数据也存在数据提高。如以上Animal a=new Cat()中,Animal是父类型,Cat是子类型,将Cat提高为Animal,称为向上转型。

  若是想要调用调用猫的特有方法(抓老鼠)时,能够强制将父类的引用转成子类对象。

  咱们能转换的是父类引用指向本身的子类对象,该引用能够被提高,也可被强制向下转换

  以下:

Animal c=new Cat();//
Cat c1=(Cat)c;        //向下转型
c1.catchMouse();    //输出猫的特有方法

 

 

 

在多态中,成员函数的特色:

一、编辑时期,参阅引用型变量所属的类中是否有调用方法。若是有编译经过,不然编译失败。

以下:Fu f = new Zi(),f所属的Fu中只有method1和method2,因此输出method3会编辑失败。

二、在运行时间,参阅对象所属的类中是否有调用方法。

以下:

Fu f = new Zi();
f.method1();
f.method2();

调用的是Zi类的方法,

简单总结,成员函数在多态调用时,编辑看左边,运行看右边

以下:

Fu类有method1和method2两个方法

Zi类中有method1和method3两个方法

Zi类中method1复写了Fu类中的method1,Zi类有三个方法

 

 

package com.duotai2;

public class DuoTaiDemo {

    public static void main(String[] args) {
        Fu f = new Zi();
        f.method1();
        f.method2();
        // f.method3();   //编译失败     

    }

}

class Fu {
    void method1() {        //
        System.out.println("fu_method_1");
    }

    void method2() {        //
        System.out.println("fu_method_2");
    }
}

class Zi extends Fu {
    void method1() {        //复写
        System.out.println("zi_method_1");
    }

    void method3() {        //
        System.out.println("zi_method_3");
    }

}

输出:

zi_method_1
fu_method_2

 

 

在多态中,成员变量的特色:

不管编辑和运行,只参考左边。以下

package com.duotai2;

public class DuoTaiDemo {

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

class Fu {
    int num=5;
}

class Zi extends Fu {
    int num=8;
}

输出:

5

8

 

在多态中,静态成员函数的特色:

不管编辑和运行,只参考左边。由于静态方法不须要建立对象,只要类名调用便可。

以下

public class DuoTaiDemo {

    public static void main(String[] args) {
        Fu f = new Zi();
        f.method4();
        
        Zi z=new Zi();
        z.method4();
    }
}

class Fu {
    static void method4() {        //
        System.out.println("fu_method_4");
    }
}

class Zi extends Fu {
  static void method4() {        //
        System.out.println("zi_method_4");
    }

}

输出:

fu_method_4zi_method_4

相关文章
相关标签/搜索