• 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  }
  • 相关阅读:
    leetcode 29-> Divide Two Integers without using multiplication, division and mod operator
    ros topic 发布一次可能会接收不到数据
    python中的print()、str()和repr()的区别
    python 部分函数
    uiautomatorviewer错误 unable toconnect to adb
    pyqt 不规则形状窗口显示
    appium 计算器demo
    Spring 3.0 注解注入详解
    Spring Autowire自动装配
    restful 学习地址
  • 原文地址:https://www.cnblogs.com/qjack/p/3225027.html
Copyright © 2020-2023  润新知