zoukankan      html  css  js  c++  java
  • Delphi的类和对象(八)- 多态

    先简单理解下面示例:

    什么是多态? 我的理解就是: 同样一个方法, 在不同的对象里会有不同的实现, 仅此而已.
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        Button3: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
      end;
    
      //定义了三个类, 后两个类都继承与第一个类 TBass
      TBass = class
        procedure alert; virtual; {加上 virtual 指示字, 说明这个方法可能会被修改(或叫覆盖)}
        {这种方法叫虚方法}
      end;
    
      TChild1 = class(TBass)
        procedure alert; override; {override 表示修改父类的同名方法}
      end;
    
      TChild2 = class(TBass)
        procedure alert; override;
      end;
    
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    { TBass }
    procedure TBass.alert;
    begin
      ShowMessage('is Bass');    {同一个方法, 在不同类里有不同的实现}
    end;
    
    { TChild1 }
    procedure TChild1.alert;
    begin
      ShowMessage('is TChild1'); {同一个方法, 在不同类里有不同的实现}
    end;
    
    { TChild2 }
    procedure TChild2.alert;
    begin
      ShowMessage('is TChild2'); {同一个方法, 在不同类里有不同的实现}
    end;
    
    
    //测试1:
    procedure TForm1.Button1Click(Sender: TObject);
    var
      bass: TBass; {定义 TBass 的变量}
    begin
      bass := TBass.Create;
      bass.alert; {is Bass}
      bass.Free;
    end;
    
    //测试2:
    procedure TForm1.Button2Click(Sender: TObject);
    var
      bass: TBass;            {注意还是定义 TBass 的变量}
    begin
      bass := TChild1.Create; {但这里是通过 TChild1 建立对象}
      bass.alert; {is TChild1}
      bass.Free;
    end;
    
    //测试3:
    procedure TForm1.Button3Click(Sender: TObject);
    var
      bass: TBass;            {注意还是定义 TBass 的变量}
    begin
      bass := TChild2.Create; {但这里是通过 TChild2 建立对象}
      bass.alert; {is TChild2}
      bass.Free;
    end;
    
    {总结: 现在同是 bass.alert 方法, 通过不同对象的实现, 有了不同的功能, 这就是多态!}
    end.

    多态可以是一个类变化出很多不同的形态,重载和虚方法是多态的主要实现方式。父类使用标识符 virtual 定义虚方法,子类继承父类并使用标识符 override 覆盖虚方法。

    类对象的向上转换就是一种堕胎的表现形式,上面的例子就是向上转换的概念。

    由于子类包含了父类所有的特性,所以可以将子类的对象赋予给父类的变量。那么这时父类就可以表现出多种形态。

    再比如,将人这个类定义为父类TPerson ,中国人,美国人,英国人三个类定义为子类。那么创建的这三个字类的对象都可以赋值给父类变量。实现多态,也就向上转换(子类转父类)。 

    当在子类中覆盖或重载父类的方法时(同名),如何调用父类的同名静态方法和虚方法呢?

    思考:

    (1)回忆前面讲到的重载与虚方法,首先如果子类定义了与父类同名的静态方法,也就是重载(后加overload )。那么调用的是子类本身的静态方法。

    (2)父类中定义好虚方法之后,如果子类中定义了一个同名的方法,那么调用时子类的方法就不会像静态方法那样去覆盖父类的同名方法,而是在继承父类原有方法的基础上展现自身方法的特性。

        对虚方法的覆盖也叫重载(override)。

    在子类如何调用父类的方法呢,需要关键字 inherited 来调用所继承的父类方法。inherited就是调用祖先类的函数,如果不带参数就是默认调用同名函数

    Inherited 的使用有三种情况:

    一、在子类中没有重载或覆盖父类的方法时调用父类的方法。

    二、当子类覆盖父类的方法时调用父类的方法。

    三、当子类重载了父类的方法时调用父类的方法。(二 三使用方法一样)。

    {它的完整语法是inherited XXX(ParamList);。
    上面的语法表示调用父类的方法XXX, ParamList是参数列表。
    如果直接使用inherited,没有指定方法名和参数,那么就会调用父类的同名方法。
    
    inherited Create(AOwner); 和直接写inherited有区别吗 
    
    有区别,inherited Create是指定调用父类的Create方法,当然你也可以inherited Destory等等,
    如果直接写inherited则默认以本方法名在父类中调用
     
     
    inherited就是调用祖先类的函数,如果不带参数就是默认调用同名函数
    如果带参数则表明子类中的函数个数可能比祖先类要多取其中的几个参数传过去
    例如
    祖先类有个函数 Create(AName:string);
    子类有个函数 Create(AName:string;AComponent:TObject);override;
    那么子类的Create函数内就可以这样调用祖先类:}
    procedure TAClass.Create(AName:string;AComponent:TObject);
    begin
        Inherited Create(AName);
    end;

    部分内容整理于:https://www.cnblogs.com/del/archive/2008/01/11/1034529.html

            http://www.delphitop.com/html/hanshu/3253.html

  • 相关阅读:
    FastMM、FastCode、FastMove的使用(图文并茂)
    12种JavaScript MVC框架之比较
    十款最佳Node.js MVC框架
    Couchbase 服务器
    C#程序员阅读的书籍
    ORM的实现
    Linux内核策略介绍
    ASP.NET MVC + EF 利用存储过程读取大数据
    面向.Net程序员的dump分析
    动态加载与插件化
  • 原文地址:https://www.cnblogs.com/fansizhe/p/12723845.html
Copyright © 2011-2022 走看看