zoukankan      html  css  js  c++  java
  • java/C#多态漫谈

    最近面试深受打击,我感到自己的内功不足。于是翻看了一下《java编程思想》,对多态有了更深的认识。

    以前只知道多态有什么用,怎么用,但是不知道多态的原理是什么,现在大概是知道了,我也不想私藏,现与大家分享,老鸟就不用看了。

    多态实现的原理就是“方法调用后期绑定”。

    什么叫后期绑定?

    讲一个方法调用同一个方法主体关联起来被称作绑定。若在程序执行前进行绑定(例如编译的时候)的话,叫做前期绑定(c语言都是前期绑定)。相应的,在运行时候根据对象的类型进行绑定叫后期绑定,也叫动态绑定。也就是说,如果一个语言想实现后期绑定,就必须具有某种机制,以便能够在运行时能判断对象的类型,从而调用恰当的方法。也就是说,编译器一直不知道对象的类型,但是运行时方法调用机制能够找到正确的方法体,并加以调用。不管怎样,都必须在对象中安置某种类型信息。

    在java中,除了static方法和final方法(private方法属于final方法)之外,其他的都默认进行后期绑定(就是可以多态)。如果将一个方法声明为final或者static或者private,就告诉编译器不需要对该方法动态绑定。这样,编译器就可以可以为final方法调用生成更有效的代码()。

    总结一下:

    1. java普通方法默认都是动态绑定的。

    2. 父类static 和final方法(private除外),子类不可以重写,编译器会报错。其中构造器默认是static的。

    3. 父类private(也默认final的)方法,子类可以声明同名方法(这个方法和父类同名方法只是名字相同,没有什么关系),但是不会多态,也不可能多态,因为父类方法为private的。

    4. 子类需要多态的方法的可视范围(protected , public等)不能比父类的那个方法小(可以大),否则的话,父类可能没法找到子类的那个方法,会编译时报错。

    5. java的各种属性不能多态。多态仅适用于方法。

    下面看一个例子

    复制代码
     1  class Base{
     2       
     3       public int a=2;
     4       public void fmethod(){
     5           System.out.println("base:fmethod");
     6       }
     7       int getA(){
     8           return a;
     9       }
    10   }
    11   
    12   class Sub extends Base{
    13       public int a=3;
    14       public void fmethod(){ //final表示不尽兴多态
    15           System.out.println("sub:fmethod");
    16       }
    17       //子类方法可视范围可以扩大
    18       public int getA(){
    19           return a;
    20       }
    21   }
    22   public class Test {
    23   
    24       public static void main (String args []) {
    25           Base  b=new Sub();
    26           //方法多态,输出sub:fmethod
    27           b.fmethod();
    28           //属性不能多态,输出为2.
    29           System.out.println(b.a);
    30           //但是可以通过方法来实现属性的多态,输出3
    31           System.out.println(b.getA());
    32       }
    33     
    34   }
    复制代码

    C#和java的多态机制大部分是一样的,只是有一点,有着翻天覆地的不同。

    不同:java普通方法默认是后期绑定的,而C#方法默认是前期绑定的,所以C#里面如果需要后期绑定(即多态),那么必须使用virtual + override+overide关键词对。另一方面,好像重写(这篇文章 所谓重写 ,表示需要多态的用override修饰的)的方法访问限制必须一致,不一致就报错,不清楚这个说法对不对。

    闲话少数,上代码

    复制代码
     1 class Base{
     2      
     3      public int a=2;
     4      public void fmethod(){
     5          Console.WriteLine("base:fmethod");
     6      }
     7      //virtual关键词,可以提示编译器这个方法可以被后面的子类重写(子类方法需有override),
     8      public virtual  void gmethod()
     9      {
    10          Console.WriteLine("base:gmethod");
    11      }
    12  
    13      public virtual void hmethod()
    14      {
    15          Console.WriteLine("base:hmethod");
    16      }
    17      protected virtual int getA()
    18      {
    19          return a;
    20      }
    21  }
    22  
    23  class Sub: Base
    24  {
    25      public  int a=3;
    26      //普通方法默认修饰符为new,  public void fmethod = public new void fmethod
    27      public void fmethod(){ 
    28          Console.WriteLine("sub:fmethod");
    29      }
    30      //有override,与父类virtual 配对,多态
    31      public override void gmethod()
    32      {
    33          Console.WriteLine("sub:gmethod");
    34      }
    35      //即使父类方法有virual,子类方法没有override,不会多态,
    36      public  void hmethod()
    37      {
    38          Console.WriteLine("sub:hmethod");
    39      }
    40  
    41  
    42      //子类重写的方法访问限制必须一致,对不对?
    43      protected override int getA(){
    44          return a;
    45      }
    46  }
    47  
    48  class Subsub : Sub
    49  {
    50      //有override,与父类virtual 配对,多态
    51      public override void gmethod()
    52      {
    53          Console.WriteLine("subsub:gmethod");
    54      }
    55      public static void Main(String[] args)
    56      {
    57          Base b = new Sub();
    58          //输出base:fmethod
    59          b.fmethod();
    60          //输出sub:gmethod
    61          b.gmethod();
    62          //输出base:hmethod
    63          b.hmethod();
    64          //属性不能多态,输出为2.
    65          Console.WriteLine(b.a);
    66          Sub s = new Subsub();
    67          //输出subsub:gmethod
    68          s.gmethod();
    69      }
    70    
    71  }
  • 相关阅读:
    P3193 [HNOI2008]GT考试(KMP+矩阵乘法加速dp)
    P2606 [ZJOI2010]排列计数
    洛谷P2657 [SCOI2009]windy数
    P2602 [ZJOI2010]数字计数(递推)
    洛谷 P1073 最优贸易
    [一本通学习笔记] 字典树与 0-1 Trie
    [一本通学习笔记] KMP算法
    [一本通学习笔记] 字符串哈希
    [一本通学习笔记] 广度优先搜索和优化
    [一本通学习笔记] 深度优先搜索与剪枝
  • 原文地址:https://www.cnblogs.com/qjack/p/3225027.html
Copyright © 2011-2022 走看看