• Delphi之virtual,dynamic,abstract,override,overload


    Delphi之virtual,dynamic,abstract,override,overload

    Delphi之virtual,dynamic,abstract,override,overload,reintroduce的用法

    1.方法的重写Overriding和重载Overloading是Java多态性的不同表现。

    重写Overriding是父类与子类之间多态性的一种表 现,重载Overloading是一个类中多态性的一种表现。

    如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方 法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

    2. Delphi 的函数覆盖(Override)与重载(overload)
       而Delphi 就是用override 关键字来说明函数覆盖的。被覆盖的函数必须是虚(virtual)的,或者是动态(dynamic)的,也就是说该函数在声明时应该包含这两个指示字中的一个,比如:
    procedure Draw; virtual;
    在需要覆盖的时候,只需要在子类中用override 指示字重新声明一下就可以了。
    procedure Draw; override; 

     3.virtual 虚类型
         dynamic 动态
         overload 重载
         override 重写    

    4.关于方法定义关键字的说明:
        如果在过程定义声明时包括了的关键字的含义:
        static 表示是静态方法;静态方法是方法的缺省类型,不能被覆盖;
        virtual 表示是虚拟方法;
        dynamic 表示是动态方法;
        这两类方法的共同点是都可以被覆盖(override),区别仅在于运行时调用方法时的派发机
    制,virtual方法为执行速度做了优化,而dynamic方法则为代码大小做了优化;经常被覆盖的
    方法应该定义为virtual方法;
        message 表示是消息处理方法;在关键字message后面的值指明了这个方法要响应的消息;
    用消息处理方法来响应Windows的消息,这样就不用直接来调用它;
        override 表示是覆盖方法;要求祖先类中必须有该方法的定义,并且参数的顺序和类型
    及返值的类型必须匹配;用于扩展祖先类中的该方法而不是取代它(如不调用祖先类中的该方
    法则等同于取代);
        overload 表示是重载方法;用于一个类中有许多同名的方法带着不同的参数表的情形;
    (属性的读写方法不能被重载);
        abstract 表示是抽象方法;是没有实现的方法,并且必须是virtual或dynamic方法,即
    在abstract前面必须有virtual或dynamic关键字,其实现部分在派生类中;如
          procedure DoSomething; virtual; abstract;
          reintroduce表示是重新声明的方法;用于方法的名称与祖先类中的某个方法名称相同的情形; 
       

    5.virtual 和 dynamic定义的虚函数,都是为了子类override用的,只不过它们的实现不一样。vitrual 占用的空间大点,但速度快些。dynamci

    正好相反


    从《Delphi_5开发人员指南》中抄一节给你: 
      2.18.1   方法的类型   
              对象的方法能定义成静态(static)、虚拟(virtual)、动态(dynamic)或消息处理(message)。请看下面  
      的例子:       
              TFoo    class  
                  procedure   IAmAStatic;  
                  procedure   IAmAVirtual;   virtual;  
                  procedure   IAmADynamic;   dynamic;  
                  procedure   IAmAMessage(var   M:TMessage);   message   wm_SomeMessage;  
              end;  
               
          1.   静态方法  
              IAmAStatic   是一个静态方法,静态方法是方法的缺省类型,对它就像对通常的过程和函数那样调  
      用。编译器知道这些方法的地址,所以调用一个静态方法时它能把运行信息静态地链接进可执行文件。  
      静态方法执行的速度最快,但它们却不能被覆盖来支持多态性。  
       
          2.   虚拟方法  
              IAmAVirtual   是一个虚拟方法。虚拟方法和静态方法的调用方式相同。由于虚拟方法能被覆盖,在  
      代码中调用一个指定的虚拟方法时编译器并不知道它的地址。因此,编译器通过建立虚拟方法表(VMT)  
      来查找在运行时的函数地址。所有的虚拟方法在运行时通过VMT来调度,一个对象的VMT表中  
      除了自己定义的虚拟方法外,还有它的祖先的所有的虚拟方法,因此虚拟方法比动态方法用的内存要  
      多,但它执行得比较快。  
       
          3.   动态方法  
              IAmADynamic   是一个动态方法,动态方法跟虚拟方法基本相似,只是它们的调度系统不同。编译  
      器为每一个动态方法指定一个独一无二的数字,用这个数字和动态方法的地址构造一个动态方法表  
      (DMT)。不像VMT表,在DMT表中仅有它声明的动态方法,并且这个方法需要祖先的DMT表来访问  
      它其余的动态方法。正因为这样,动态方法比虚拟方法用的内存要少,但执行起来较慢,因为有可能  
      要到祖先对象的DMT中查找动态方法。  
       
          4.   消息处理方法  
              IAmAMessage   是一个消息处理方法,在关键字message后面的值指明了这个方法要响应的消息。  
      用消息处理方法来响应Windows的消息,这样就不用直接来调用它。  
       
          5.   方法的覆盖  
              在Object   Pascal覆盖一个方法用来实现OOP的多态性概念。通过覆盖使一方法在不同的派生类间  
      表现出不同的行为。Object   Pascal中能被覆盖的方法是在声明时被标识为virtual或dynamic的方法。为  
      了覆盖一个方法,在派生类的声明中用override代替virtual或dynamic。例如,能用下面的代码覆盖  
      IAmAVirtual和IAmADynamic方法:  
       
              TFooChild    class(TFoo)  
                  procedure   IAmAVirtual;   override;  
                  procedure   IAmADynamic;   override;  
                  procedure   IAmAMessage(var   M:TMessage);   message   wm_SomeMessage;  
              end;  
       
      用了override关键字后,编译器就会用新的方法替换VMT中原先的方法。如果用virtual或dynamic替换  
      override重新声明IAmAVirtual和IAmADynamic,将是建立新的方法而不是对祖先的方法进行覆盖。同样,  
      在派生类中如果企图对一个静态方法进行覆盖,在新对象中的方法完全替换在祖先类中的同名方法。  
       
          6.   方法的重载  
              就像普通的过程和函数,方法也支持重载,使得一个类中有许多同名的方法带着不同的参数表,  
      能重载的方法必须用overload指示符标识出来,可以不对第一个方法用overload。下面的代码演示了一  
      个类中有三个重载的方法:  
       
              type  
                  TSomeClass    class  
                      procedure   AMethod(I:Integer);   overload;  
                      procedure   AMethod(I:String);   overload;  
                      procedure   AMethod(I:Double);   overload;  
                  end;  
       
          7.   重新引入方法名称  
              有时候,需要在派生类中增加一个方法,而这个方法的名称与祖先类中的某个方法名称相同。在  
      这种情况下,没必要覆盖这个方法,只要在派生类中重新声明这个方法。但在编译时,编译器就会发  
      出一个警告,告诉你派生类的方法将隐藏祖先类的同名方法。要解决这个问题,可以在派生类中使用  
      reintroduce指示符,下面的代码演示了reintroduce指示符的正确用法:  
              type  
                  TSomeBase    class  
                      procedure   Cooper;  
                  end;  
                  TSomeClass    class(TSomeBase)  
                      procedure   Cooper;   reintroduce;  
                  end;  
                   
          8.   Self  
              在所有对象的方法中都有一个隐含变量称为Self,Self是用来调用方法的指向类实例的指针。Self  
      由编译器作为一个隐含参数传递给方法。 


  • 相关阅读:
    DI 之 3.4 Bean的作用域(捌)
    DI 之 3.3 更多DI的知识(柒)
    MySQL中基本的多表连接查询教程
    DI 之 3.3 更多DI的知识(陆)
    字符串(string)转json
    如何查看连接mysql的ip地址
    DI 之 3.2 循环依赖 (伍)
    DI 之 3.1 DI的配置使用(肆)
    IoC 之 2.3 IoC的配置使用(叁)
    MySQL for Windows 解压缩版配置安装
  • 原文地址:https://www.cnblogs.com/luckForever/p/7255167.html
Copyright © 2020-2023  润新知