关于多态的理解

本文是本人在学习多态的时候对于多态的一点理解,当笔记用,如有不正之处,望请指点

多态的前提:
  • 要有方法重写
  • 要有继承关系
  • 要有父类引用子类对象(向上转型)
     格式  父类 对象名 = new 子类()
     例如   father f = new son()

多态中成员的访问特点
          成员变量
                        编译看左边(父类),运行看左边(父类)
          成员方法
                         编译看左边(父类),运行看右边(子类)
                         (因为子类成员方法存在方法重写,所以运行时用的子类,前提是子类和父类重写了同一方法,如果一个方法
                              在父类中有而子类中没有,就会调用父类中的那个方法)
          静态方法
                         编译看左边(父类),运行看左边(父类)
                         (因为静态是和类相关的,所以算不上重写,所以运行还是用的父类中的)

理解父类引用指向子类对象
     要理解父类引用指向子类对象,首先要理解向上转型,比如,father f = new son()中, 表示定义了一个father类型的引用,指向新建的son类型的对象。由于son是继承自它的父类father,所以father类型的引用是可以指向son类型的对象的,
那么这样做有什么意义呢?因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特,  定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。
 所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的方法,它是无法调用的同时,父类中的一个方法只有在父类中定义而在子类中没有重写的情况下,才可以被父类类型的引用调用,对于父类中定义的方法,如果子类中重写了该方法,那么父类类型的引用将会调用子类中的这个方法,这就是动态连接。也可以叫做动态绑定动态绑定是指”在执行期间(而非编译期间,判断所引用对象的实际类型,根据实际的类型调用其相应的方法。
向下转型: 把已经指向子类对象的父类引用(这里可以理解成已经向上转型过的f)赋给子类引用叫向下转型,son s= (son) f ,这里要求必须是f是能够转化成son的,即f已经指向了son对象(这个是基本要求)
举个例子:有2个类,father是父类,son类继承自father。
father f1 = new son();   // 这就叫 upcasting (向上转型),现在f1引用指向一个son对象
son s1 = (son)f1;   // 这就叫 downcasting (向下转型),现在f1还是指向son对象

第2个例子:

father f2 = new  father();

son s2 = (son)f2;       // 出错,子类引用不能指向父类对象
因为f1指向一个子类son对象,father f1 = new Son(),子类s1引用可以指向子类对象了。
而f2 被传给了一个Father对象,father f2 = new father(),子类s1引用不能指向父类对象
总结:
1.父类引用指向子类对象,而子类引用不能指向父类对象。
2把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转换。
      如:father f1 = new son();
3.把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转换。
   如:f1 就是一个指向子类对象的父类引用。把f1赋给子类引用s1即 son s1 = (son)f1;
           其中f1前面的(Son)必须加上,进行强制转换。

程序示例
packagehello;
classfather{
     intnum =10;
     intnum2 =55;
     publicvoidtest(){
          System.out.println("父类方法1");
     }
     publicvoidtest2(){
          System.out.println("父类方法2");
     }
     publicstaticvoidtest3(){
          System.out.println("父类静态方法");
     }
     publicvoidte(){
          System.out.println("父类特有方法");
     }
}
classsonextendsfather{
     intnum =20;
     intnum2 =99;
     intnum3 =66;//num3是子类中特有的变量
     publicvoidtest(){
          System.out.println("子类方法1");
     }
     publicvoidtest2(){
          System.out.println("子类方法2");
     }
     publicstaticvoidtest3(){
          System.out.println("子类静态方法");
     }
     publicvoidmetod(){
          System.out.println("子类特有方法");
     }
}
classDemo
{
publicstaticvoidmain(String[]args)
{
     fatherf=newson();//向上转型,让父类引用指向一个子类对象,使得可以使用被父类定义过的子类的功能(未定义的不能使用)
   
     sons=(son)f;//向下转型,强制类型转换,引用f指向一个son对象,使得可以访问son中未被父类定义过的子类特有的方法和变量
   
     f.test();//调用子类中父类已经定义过的方法
   //f.metod();//报错,因为父类中没有该方法,这种方式无法调用
   
     s.metod();//这里不会报错,因为s是强制转换后的子类对象,所以可以访问子类特有方法
   f.te();//因为子类中没有te()方法,所以在父类中调用这个方法
   f.test3();//因为test3是静态方法,静态方法运行看右边,与类关联,所以这里是父类的静态方法
   s.test3();//同上
   
    System.out.println(f.num);//成员变量中运行看右边,所以是父类中的变量
    System.out.println(s.num);//访问子类中特有的变量
    System.out.println(f.num2);
    System.out.println(s.num2);
   //System.out.println(f.num3);//因为num3是子类中特有的变量,而变量运行看父类(左边),所以通过这种方式无法访问
    System.out.println(s.num3);//因为s指向子类,这种方式可以访问num3不会报错
   
     
}
}


运行结果
子类方法1
子类特有方法
父类特有方法
父类静态方法
子类静态方法
10
20
66


多态的利弊
多态的好处:
        A:提高了代码的维护性(继承保证)
        B:提高了代码的扩展性(由多态保证)
多态的弊端
      A:如果不进行向下转型无法使用子类的特有功能



对于多态,可以总结它为:       


     一、使用父类类型的引用指向子类的对象;

    二、该引用只能调用父类中定义过的方法和变量;


    三、如果子类中重写了父类中的一个方法,那么在调用这个方法的时候,将会调用子类中的这个方法;(动态连接、动态调用)

    四、变量不能被重写(覆盖),”重写“的概念只针对方法,如果在子类中”重写“了父类中的变量,那么在编译时会报错。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值