zoukankan      html  css  js  c++  java
  • 重载,覆盖,多态

    一、override  重载
    type
      TFigure = class
        procedure Draw; virtual;//(我的理解是)父类中可以使用父类的,子类中使用子类的。与“四”是有区别的。
      end;
      TRectangle = class(TFigure)
        procedure Draw; override;//a1
      end;
      TEllipse = class(TFigure)
        procedure Draw; override;//a2
      end;
    使用
    var
      Figure: TFigure;
    begin
      Figure := TRectangle.Create;
      Figure.Draw;  // 执行a1
      Figure.Destroy;
      Figure := TEllipse.Create;
      Figure.Draw;  // 执行a2
    end;
     
    二、overload 多态
      procedure foo(i: integer); overload;
      procedure foo(d: double);  overload;
      procedure foo(v: variant); overload;
    典型用法。如果是对于继承的。必须使用reintroduce
    type
      T1 = class(TObject)
        procedure Test(I: Integer); overload; virtual;
      end;
      T2 = class(T1)
        procedure Test(S: string); reintroduce; overload;
      end;
       ...
      SomeObject := T2.Create;
      SomeObject.Test('Hello!');  // T2.Test
      SomeObject.Test(7);         // T1.Test
     
    三、override & inherited
    override是用来重载父类的procedure,
    如果父类是virtual 或者 dynamic 方法的,就可以使用inherited,来调用父类中的代码。
     
    四、abstract
    procedure DoSomething; virtual; abstract;//如果是这个样式的,表示要在子类中实现(代码)。而父类中,其他procedure function可以使用这个procedure。
    (这里的virtual似乎不能被dynamic替换)。
    使用procedure DoSomething; virtual; abstract;和procedure DoSomething; virtual;的区别就是,前者的实现代码在子类,而后者实现代码在自身。后者可以在子类中override一下,使其子类也有自己的实现代码。
    2009-4-11
    在最近的代码中发现(不知道是不是D7的缘故)
    procedure DoSomething; virtual; abstract;
    procedure DoSomething; dynamic; abstract;
    都是可以的。
    而且在继承类中也可以不写实现代码。
    在基类中如果要判断有没有被继承类写实现代码的方式不是
    if Assigned(DoSomething) then ...
    而是
    if MethodAddress('DoSomething')<>nil then...
     
    五、reintroduce
    覆盖父类中的virtual 方式的内容。(编译器不会提示“xxx 被hide了”)
     
    六、static
    默认就是这个。
    我们常打 procedure test(xx:Integer);其实就是static的。
    这个比较好理解。
    如果子类中,声明了一个test,跟父类无关。各自用各自的。
    除非使用强制转换。比如:
    type
      TFigure = class
        procedure Draw;
      end;
      TRectangle = class(TFigure)
        procedure Draw;
      end;
    //实现
    var
      Figure: TFigure;
      Rectangle: TRectangle;
    begin
      Figure := TFigure.Create;
      Figure.Draw;  // 父类用父类的 TFigure.Draw
      Figure.Destroy;
      Figure := TRectangle.Create;
      Figure.Draw;  // 虽然初始化为子类,但是由于申明的是父类,所以Figure还是调用了父类的Draw  TFigure.Draw
      TRectangle(Figure).Draw;  // 强制转换成子类,就可以用TRectangle.Draw
      Figure.Destroy;
      Rectangle := TRectangle.Create;
      Rectangle.Draw;  // 子类用子类的 TRectangle.Draw
      Rectangle.Destroy;
    end;
     
    七、forward declaration提前定义。
    用于类被提前使用。注意fd的class后面要立即加“;”不能使用括号和基类。
    type
      TFigure = class;  // forward declaration
      TDrawing = class
        Figure: TFigure;
         ...
      end;
      TFigure = class  // defining declaration
        Drawing: TDrawing;
         ...
      end;
     
    八、virtualdynamic
    虚拟方法占用的内存大,调用速度快;动态方法相反。
    如今,哪有PC内存不够的。
    所以,笔者建议,就使用virtual吧。
    2009-04-07
    我知道了,内存是有不够用的时候。
    所以这里修改说法,需要来回调用的用virtual,一般只用到1,2次的用dynamic。
    像笔者一般写一个基类函数,只用一次,所以大部分都改成dynamic了。
    但是有个地方必须要用virtual
    private
      FItem:Integer
      procedure SetItem(Value:Integer);virtual;//dynamic不允许
    public
      property Item:Integer;read FItem write SetItem;
    end;
    View Code

  • 相关阅读:
    转自一位前辈的杂谈
    在vim编辑器中实现python的tab补全
    Go语言 异常panic和恢复recover用法
    go语言的cron包的简单使用
    go语言的指针
    Python 报 OpenSSL.SSL.SysCallError: (10054, 'WSAECONNRESET')
    python 之图像处理
    git 线上连接及版本控制
    vue依赖pycharm启动
    模拟django 后台管理
  • 原文地址:https://www.cnblogs.com/key-ok/p/3380401.html
Copyright © 2011-2022 走看看