java_se 多态

来源:互联网 发布:超市美工是做什么的 编辑:程序博客网 时间:2024/06/07 06:43

1 概念
多态:一个事物在不同时刻体现出来的不同状态:
如:
水:固态,汽态 ,液态
Animal a = new Cat() ;
Animal a = new Dog() ;
2实现条件
* 条件1:必须有继承关系(如果没有继承关系,谈不上多态!)
* 条件2:必须有方法重写
* 子类出现了父类一样的 方法声明
* 条件2:有父类引用指向子类对象:向上转型
* Fu f = new Zi() ;
* 多态的三个条缺一不可!
3多态的成员访问特点:
* 成员变量:
* 编译看左边,运行看左边
* 成员方法(非静态的成员方法):
* 编译看左,运行看右;由于存在方法重写,所以就运行最终的就是子类的成员方法
* 静态成员方法:(静态方法算不上方法重写,静态直接跟类有关系!)
* 编译看左,运行看左
* 构造方法:还是对象进行初始化,由于是一种继承关系,还是分层初始化!
4多态的好处(特点):
*
* 1)提高代码的维护性(由继承保证)
* 2)提高代码的扩展性(由多态保证)
* java的开发原则:低耦合,高内聚
5案例 one (编译运行的测试)

class Fu{    public int num = 10 ;    //父类的成员方法    public void show(){        System.out.println("show Fu...");    }    //静态方法    public static void function(){        System.out.println("function Fu....");    }}//子类class Zi extends Fu{    int num = 20 ;    public void show(){        System.out.println("show Zi...");    }    public static void function(){        System.out.println("function Zi....");    }}//测试类public class DuoTaiDemo {    public static void main(String[] args) {        //创建父类的对象:多态的形式//      有父类引用指向子类对象:向上转型        Fu f = new Zi() ;        //访问成变量 编译看左,运行看左        System.out.println(f.num);        //调用成员方法:show()   编译看左,运行看右        f.show() ;        //静态方法  编译看左,运行看左        f.function() ;}}//运行结果  10show Zi...function Fu....

案例two(初步多态体验)

class Animal{    public void eat(){        System.out.println("eat");    }    public void sleep(){        System.out.println("sleep...");    }}//猫类class Cat extends Animal{    public void eat(){        System.out.println("猫吃鱼...");    }    public void sleep(){        System.out.println("猫趴着睡...");    }}//狗类class Dog 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("猪卧着睡....");    }}-------------------以下这个工具类很能体现多态的特点,很用用的!!!!!!!!---------------//写一个动物的工具类 记住一些工具类的特点(私有构造,static方法)class AnimalTool{    //将类中无参构造私有化:目的是为了不让外界创建对象!    /*private AnimalTool(){    }*/    //形式参数是一个父类    public  static void  useAnimal(Animal a){        a.eat() ;        a.sleep() ;    }}//测试类public class DuoTaiDemo2 {    public static void main(String[] args) {        //下面代码很繁琐        //我喜欢猫,养一只猫        Cat c1 = new Cat() ;        c1.eat() ;        //还喜欢猫,又养了一只        Cat c2 = new Cat() ;        c2.eat() ;        //...        Cat c3 = new Cat() ;        c3.eat() ;        System.out.println("---------------------");        //优化改进:将猫的吃和睡的方法封装成独立的功能 功能见最后        /*useCat(c1) ;        useCat(c2) ;        useCat(c3) ;*/        Dog d1 =  new Dog() ;        Dog d2 =  new Dog() ;        Dog d3 =  new Dog() ;        //调用狗的功能        /*useDog(d1) ;        useDog(d2) ;        useDog(d3) ;*/        Pig p1 = new Pig() ;        Pig p2 = new Pig() ;        Pig p3 = new Pig() ;        System.out.println("------------------------");        //最终版代码        AnimalTool.useAnimal(c1) ;//形式参数类似与:Animal a = new Cat();        AnimalTool.useAnimal(c2) ;        AnimalTool.useAnimal(c3) ;        System.out.println("-------------------------");        AnimalTool.useAnimal(d1) ;        AnimalTool.useAnimal(d2) ;        AnimalTool.useAnimal(d3) ;        System.out.println("-------------------------");        AnimalTool.useAnimal(p1) ;        AnimalTool.useAnimal(p2) ;        AnimalTool.useAnimal(p3) ;    }    //写一个功能    /*public static void useCat(Cat c){        c.eat() ;        c.sleep() ;    }    public static void useDog(Dog d){        d.eat() ;        d.sleep() ;    }*/}

6多态的弊端:
不可以访问子类特有的方法(父类没有不可以使用多态)

class Animal2{    public void show(){        System.out.println("show Animal2...");    }}//子类class Cat2 extends Animal2{    public void show(){        System.out.println("show Cat2....");    }    //特有功能    public void playGame(){        System.out.println("猫玩毛线...");    }}//测试类public class DuoTaiDemo3 {    public static void main(String[] args) {        //多态的形式:父类引用指向子类对象        Animal2 a = new Cat2() ;        a.show() ;//      a.playGame() ;  报错 因为playGame()是子类特有的方法    }}
  • 多态的弊端是不能访问子类的特有功能:如何解决?
  • 异常:OOM异常:严重:OutOfMemory:内存溢出!

    • 解决方案:
  • 1)创建子类的具体对象,来访问自己的特有功能;虽然可以解决多态的弊端,但是从内存角度考虑,需要创建子类对象,那么必须在堆内存开辟空间,
  • 耗费内存,浪费空间!
  • 2)既然多态的第三个前提条件:父类引用指向子类对象,那么可不可以将子类的引用指向父类对象呢?
  • 可以的:向下转型:将父类的引用强制转换为子类的引用:前提必须有父类的引用存在;
  • 向下转型必须依赖于向上转型!

    • */
      代码如下:
class Animal3{    public void show(){        System.out.println("show Animal2...");    }}//子类class Cat3 extends Animal3{    public void show(){        System.out.println("show Cat2....");    }    //特有功能    public void playGame(){        System.out.println("猫玩毛线...");    }}public class DuoTaiDemo4 {    public static void main(String[] args) {        //父类引用指向子类对象        Animal3 a = new Cat3() ; //向上转型        a.show() ;        //不能访问子类特有功能//      a.playGame();        //创建子类具体对象 这种方法还要创建对象,如果一开始直接用子类new 子类就没有办法使用多态    /*  Cat3 c = new Cat3() ;        c.playGame() ;*/        //父类的引用强制转换为子类的引用:向下转型        Cat3 c = (Cat3) a ;        c.playGame() ;    }}
  • 一般情况下:向下转型使用不当会造成一个异常:类转换异常
    代码如下:
class Animal4{    public void eat(){}}class Cat4 extends Animal4{    public void eat(){}    public void playGame(){}}class Dog4 extends Animal4{    public void eat(){}    public void lookDoor(){}}//测试类:public class DuoTaiDemo5 {    public static void main(String[] args) {        //内存是狗        Animal4 a = new Dog4() ;        //向下转型:还原成狗        Dog4 d = (Dog4)a ;        //内存是猫        a = new Cat4() ;        //还原成猫        Cat4 c = (Cat4) a ;        //编译通过了        Dog4 dd = (Dog4)a ; //不能将内存猫转换为狗    }}

把父类引用a 一会当作猫,一会当作狗,程序员一会就迷了,就会造成异常,所以开发过程中指将一个父类引用指向一个子类对象。

补充:如果有多层继承,最后的子类继承的方法一定是就近的上一层父类的方法!