黑马程序员————面向对象之多态

来源:互联网 发布:mac系统怎么卸载flash 编辑:程序博客网 时间:2024/05/17 01:49

------- android培训java培训、期待与您交流! ----------


众所周知,面向对象思想有三大特征:封装,继承,多态。

下面详细说说多态。

举个例子,猫对应的类型是猫类型,同时也是动物类型,很明显动物是猫的父类。我们在创建猫对象的时候,可以用:

    猫 cat = new 猫();也可以用:动物cat = new 猫();第二种方法就是父类型引用指向了子类对象。这种现象就是多态。

由此可见,多态就是同一事物在不同时刻体现出来的不同状态。

多态的体现:父类或者接口的引用指向或者接收自己的子类对象。

多态的前提:

1、  必须类与类之间有关系,要么是继承关系,要么是实现关系

2、  要有方法的覆盖

举例:class Fu {

                  public int num = 100;

 

                  public void show() {

                            System.out.println("show Fu");

                  }

        

                  public static void function() {

                           System.out.println("functionFu");

                  }

}

//继承关系

class Ziextends Fu {

         public int num = 1000;

         public int num2 = 200;

         //覆盖操作

         public void show() {

                   System.out.println("showZi");

         }

        

         public void method() {

                   System.out.println("methodzi");

         }

        

         public static void function() {

                   System.out.println("functionZi");

         }

}

class DuoTaiDemo {

         public static void main(String[] args) {

                   //父类引用指向子类对象。

                   Fuf = new Zi();

         }       

}

多态中成员访问的特点:

1、  成员变量:

编译看左边,运行也看左边。

2、  成员函数:

编译看左边,运行看右边。

3、  构造函数:

创建子类的对象的时候,访问父类的构造方法,对父类的数据进行初始化。

4、  静态函数:

编译看左边,运行也看左边。(静态是和类相关的)

举例:

class Fu {

         public int num = 100;

 

         public void show() {

                   System.out.println("showFu");

          }

        

        public static void function() {

                   System.out.println("functionFu");

         }

}

 

class Zi extends Fu {

         public int num = 1000;

         public int num2 = 200;

 

         public void show() {

                    System.out.println("showZi");

         }

        

         publicvoid method() {

                    System.out.println("methodzi");

          }

        

         public static void function() {

                   System.out.println("functionZi");

         }

}

 

class DuoTaiDemo {

         public static void main(String[] args) {

                   //父类引用指向子类对象。

                   Fu f = new Zi();

                   System.out.println(f.num);//结果为1000

                   //System.out.println(f.num2);//编译时就找不到符号

                  

                   f.show();//编译看父类有show方法,编译通过,运行时看子类有show方法,输出show Zi

                   //f.method();//编译时看父类没有method方法,编译不通过

                   f.function();//编译看父类有method方法,编译通过,运行时看子类有method方法,输出function Zi

 

         }

}

 

多态的好处:

1、  提高了代码的可维护性(由继承保证);

2、  提高了代码的可扩展性(由多态保证)

举例:

现在有父类:Animal 和两个子类:Cat和Dog;对这两个子类的对象进行维护

//父类

abstract class Animal

{

          abstract void eat();

}

//创建子类并覆盖父类方法

class Cat extends Animal

{

         public void eat()

         {

                    System.out.println("吃鱼");

         }

         public void catchMouse()

          {

                   System.out.println("抓老鼠");

        }

                  

}

//创建子类并覆盖父类方法

class Dog extends Animal

{

          public void eat()

          {

                   System.out.println("吃骨头");

          }

          public void watchHome()

         {

                   System.out.println("看家");

           }

 

}

 

class DuoTaiDemo

{

        publics tatic void main(String[] args)

         {

                   Catc = new Cat();//创建一个Cat对象

                   c.eat();//调用Cat类中的方法

                   Dogd = new Dog();//创建一个Dog对象

                   d.eat();//调用Dog类中的方法

         }

}

在此基础上,如果又增加了Pig对象,那我们可以直接创建Pig类继承Animal类,并在主函数中创建Pig对象和调用Pig类中的方     法。可见多态的出现使程序的维护和扩展变得容易。

但是发现多态有个弊端:虽然提高了扩展性,但是使用父类的引用只能访问父类中的成员,不能使用子类的特有功能。

如果要使用子类的特有功能呢?当然可以如上面的例子中这样创建子类对象然后调用方法,但是很多时候会不合理,占内存,     也是代码的重复性很高。对此java提供了另外一种方式:向下转型,即将父类的引用强制转换为子类的引用,

    格式:子类名子类对象名 = (子类名)父类对象名;

那么,我们如果要在上例中加入Pig对象,可以将创建对象和调用方法功能封装起来,并用父类引用强转为子类引用,改进的      代码如下:

abstract class Animal

{

          abstrac tvoid eat();

}

 

       class Cat extends Animal

{

         public void eat()

        {

                    System.out.println("吃鱼");

         }

         public void catchMouse()

         {

                   System.out.println("抓老鼠");

         }

                  

}

 

class Dog extends Animal

{

          public void eat()

         {

                    System.out.println("吃骨头");

         }

        public void watchHome()

         {

                   System.out.println("看家");

         }

 

}

 

class Pig extends Animal

{

         public void eat()

         {

                    System.out.println("吃饲料");

         }

         public void gongDi()

         {

                  System.out.println("拱地");

        }

 

}

 

 

 

 

 

class DuoTaiDemo

{

         public static void main(String[] args){

                   function(newCat());

                   function(newDog());

                   function(newPig());

 

         }

         //定义一个方法将建立对象和调用方法封装

          public static void function(Animal a)//形参是用父类引用接收子类对象

         {

                   a.eat();

                   if(a instanceof Cat)

                   {

                            //判断a的类型,然后强转

                            Catc = (Cat)a;

                            c.catchMouse();

                   }

                   elseif (a instanceof Dog)

                   {

                            Dogd = (Dog)a;

                            d.watchHome();

                   }

                   elseif (a instanceof Pig)

                   {

                            Pigp = (Pig)a;

                            p.gongDi();

                   }

         }

}

 

千万不能有这样的操作:Animal a = new Animal();  Catc = (Cat)a; 这样是将父类的对象转换成子类类型。我们所能转换     的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被强转。多态自始至终都是子类对象再做着变化。


0 0