郭姐姐 發表於 2022-12-4 09:58:00

delphi D11编程语言手册 学习笔记(P344-392) 接口/类操作

<img src="https://img2022.cnblogs.com/blog/981841/202211/981841-20221121110647192-1287525760.png">
<p>&nbsp;</p>
<p>&nbsp;这本书可以在 Delphi研习社②群 256456744 的群文件里找到. 书名: Delphi 11 Alexandria Edition.pdf</p>
<p>置顶: 好烧脑啊!</p>
<p><span style="font-size: 16px"><strong>P344-365 接口</strong></span></p>
<p><span style="font-size: 16px"><strong>  "接口" 的概念和 "类" 特别是 "抽象类" 近似, Delphi 之初并没有接口, 后来(Delphi 3)为了支持 COM 引入了接口, 再后来发展成为 Delphi 重要的语言特性.</strong></span></p>
<p><span style="font-size: 16px"><strong>  <span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">使用 COM 步骤可能是这样的:<br>
    1.程序在使用组件之初, 先联系 "接口"; 这应该是从注册表中查询.<br>
    2.找到后, 如果此接口还没有被实现, 马上调用 "类厂" 建立起对象, 并同时给接口计数器加 1.<br>
    3.可能会不止一个程序在使用同一个接口, 但每有使用则 "计数器+1", 每次用完则 "计数器-1".<span style="font-size: 16px"><strong><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><br>
    4.当接口的使用计数为 0 时, 系统自动释放类厂为该接口建立的对象(垃圾回收机制).</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></strong></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">下面用代码来理解这段话:</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></strong></span></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>Type <br>IFace = <span style="color: rgba(0, 0, 255, 1)">interface  //声明一个接口</span>
    <span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> proc;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

TAType </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TInterfacedObject, IFace)  //调用接口<br>   </span><span style="color: rgba(0, 0, 255, 1)">constructor</span> <span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">;  //构造函数
    </span><span style="color: rgba(0, 0, 255, 1)">destructor</span> <span style="color: rgba(0, 0, 255, 1)">Destroy</span>; <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)">;    //解析函数<br><span style="color: rgba(0, 0, 0, 1)">   <span style="color: rgba(0, 0, 255, 1)">procedure<span style="color: rgba(0, 0, 0, 1)"> proc;  //在存在构造函数或解析函数时,方法属性一律写在最后,否则出错</span></span></span>
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
Form2: TForm2;

</span><span style="color: rgba(0, 0, 255, 1)">implementation</span>

<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$R *.dfm</span><span style="color: rgba(0, 128, 0, 1)">}</span>

<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> TAType </span><span style="color: rgba(0, 128, 0, 1)">}</span>

<span style="color: rgba(0, 0, 255, 1)">constructor</span> TAType.<span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">inherited</span><span style="color: rgba(0, 0, 0, 1)">;
Form2.memo1.lines.add(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TATypeConstructor!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">destructor</span> TAType.<span style="color: rgba(0, 0, 255, 1)">Destroy</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">inherited</span><span style="color: rgba(0, 0, 0, 1)">;
Form2.memo1.lines.add(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TATypeDestroy!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TAType.proc;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Form2.memo1.lines.add(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TAType.proc!</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm2.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
A: IFace;    </span><span style="color: rgba(0, 128, 0, 1)">//注意这里,这里声明的是一个接口
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
   A:</span>= TAType.<span style="color: rgba(0, 0, 255, 1)">Create</span> ;    <span style="color: rgba(0, 128, 0, 1)">//然而这里去是用的类的构造函数,这里是接口的一个妙用.<span style="color: rgba(0, 128, 0, 1)">接口变量可以接一个实现了该接口的类 </span>
</span><span style="color: rgba(0, 0, 0, 1)">   A.proc;<br>  <span style="color: rgba(0, 128, 0, 1)">//A:=nil;    //主动释放内存,同样的,拥有它的类也会被释放掉!</span><br>&nbsp;&nbsp; Form2.memo1.lines.add('---end---');
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>&nbsp;</p>
<p><img alt="" loading="lazy" src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221204164513415-1187741125.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 16px"><strong>  与类相比,接口侧重于封装,并提供与类之间一种比继承更宽松一点的连接.</strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0">除了宣告抽象类<span class="fontstyle1">(<span class="fontstyle0">拥有抽象方法的类别<span class="fontstyle1">)<span class="fontstyle0">,在 <span class="fontstyle1">Object Pascal <span class="fontstyle0">里面我们也可以撰写<span class="fontstyle0">纯粹的抽象类<span class="fontstyle1">;<span class="fontstyle0">也就是只包含虚拟抽象方法的类别。透过使用特别的关键词,<span class="fontstyle1">interface <span class="fontstyle0">来定义一组作为接口<span class="fontstyle1">(interfaces)<span class="fontstyle0">的数据型别。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p>&nbsp;</p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">从技术面来看,接口不算是类,虽然接口可以重组类.因为类可以建立实体,但是接口不行.接口可以被一个或者多个类调用,所以这些实体就可以算是支持了或者调用了该接口.讲人话就是: <span style="color: rgba(255, 0, 0, 1)">接口是用来给类调用的抽象类.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">类与接口的对比:</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">1.  接口类型的变量会修改接口计数器,跟类类型的变量不同,接口提供了一系列的自动内存管理机制</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">2.  <span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">一个类可以继承多个接口(要列在基础类后面): </span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<div class="cnblogs_code">
<pre>  TMyClass = <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(父类, 接口1, 接口2, ...)&nbsp;
      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Some Code</span>
  <span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>  <span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">但是一个接口只能从另一个接口继承过来,而不能同时继承多个接口,如果继承的对象是根接口<span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)">Iinterface</span></span>,则可省略.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<div class="cnblogs_code">
<pre>IMyInterface1 = <span style="color: rgba(0, 0, 255, 1)">interface(<span style="color: rgba(255, 0, 0, 1)">Iinterface</span>)</span>
    <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Func1: Integer;
    </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Func2: Integer;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">3.  所有的类都是从TObject中衍生而来,所有的接口都是从IInteface衍生出来的,两都是各自独立正交的架构.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">4.  不成文约定:所有类名,除异常类型外以E开头外,其他都以T开头,而所有接口都以字母I开头.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">5.  接口只有方法与属性没有字段<br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">6.  接口成员都是公开的,不需要private/protected/public/published等修饰语</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">7.  因为接口只声明、无实现, 所以也用不到继承与覆盖相关的修饰(virtual、dynamic、abstract、override).</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">8.  不管实现接口的类有多么丰富, 接口只拥有自己声明的成员.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">9.  实现接口的类一般继承于 TInterfacedObject, 直接从 TObject 继承会增加一些麻烦而重复的工作.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">10.  接口在用完后会自动释放, 并同时释放拥有它的类; 这很方便, 但同时带来很多问题.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">11. 每个接口具有唯一的标识符,称为GUID,在接口内按下Ctrl+Shift+G,IDE会自动产生一组GUID  </span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<div class="cnblogs_code">
<pre> IFace = <span style="color: rgba(0, 0, 255, 1)">interface<br>  <span style="color: rgba(0, 0, 0, 1)">//GUID,平常是由系统分配的,所以基本不用理会.这里只是演示</span></span><span style="color: rgba(0, 0, 0, 1)">
    [</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">{E5AC8E60-2DBE-43C5-B679-27731A56F3D4}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">]  
    </span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> proc;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">接口的声明与调用:</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">  和类的声明一样,接口也是在interface区域下用关键字type进行声明:</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">unit</span><span style="color: rgba(0, 0, 0, 1)"> Unit1;

</span><span style="color: rgba(0, 0, 255, 1)">interface</span>

<span style="color: rgba(0, 0, 255, 1)">uses</span><span style="color: rgba(0, 0, 0, 1)">
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls;

</span><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
TForm1 </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TForm)
    Memo1: TMemo;
    Button1: TButton;
    </span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">private</span>
    <span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> Private declarations </span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">public</span>
    <span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> Public declarations </span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">接口只有属性和方法,没有字段!并且只能继承一个祖先,如果是根接口,可以省略不写</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">接口1   </span>
IFace1 = <span style="color: rgba(0, 0, 255, 1)">interface</span>
    <span style="color: rgba(0, 0, 255, 1)">function</span> Fn1(Str: <span style="color: rgba(0, 0, 255, 1)">string</span>): <span style="color: rgba(0, 0, 255, 1)">string</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">抽象方法,只有声明没有实体,<span style="color: rgba(0, 128, 0, 1)">按Ctrl+Shift+c无响应</span></span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">接口2</span>
IFace2 = <span style="color: rgba(0, 0, 255, 1)">interface</span>
    <span style="color: rgba(0, 0, 255, 1)">procedure</span> Proc2;    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">抽象方法,只有声明没有实体<span style="color: rgba(0, 128, 0, 1)">,<span style="color: rgba(0, 128, 0, 1)">按Ctrl+Shift+c无响应</span></span></span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">类调用上面的两个接口,注意先后顺序,先类,后接口,不然报错.<br><span style="color: rgba(255, 0, 0, 1)">//接口里有什么方法,调用的类里面就要定义什么方法,说白了就是抄一份下来</span><br><span style="color: rgba(255, 0, 0, 1)">//否则会提示 接口方法 IFace1.test 没有实现部分</span></span>
TAType = <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TInterfacedObject, IFace1, IFace2)  //先类后接口
   </span><span style="color: rgba(0, 0, 255, 1)">function</span> Fn1(Str: <span style="color: rgba(0, 0, 255, 1)">string</span>): <span style="color: rgba(0, 0, 255, 1)">string</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这里要按Ctrl+Shift+c来完成方法实体</span>
    <span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> Proc2;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
Form1: TForm1;

</span><span style="color: rgba(0, 0, 255, 1)">implementation</span>

<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$R *.dfm</span><span style="color: rgba(0, 128, 0, 1)">}</span>

<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> TAType </span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">方法实体</span>
<span style="color: rgba(0, 0, 255, 1)">function</span> TAType.Fn1(str: <span style="color: rgba(0, 0, 255, 1)">string</span>): <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Result :</span>= (<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Fn1:</span><span style="color: rgba(128, 0, 0, 1)">'</span> +<span style="color: rgba(0, 0, 0, 1)"> str);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">方法实体</span>
<span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TAType.Proc2;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
ShowMessage(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Fn2</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
TA: TAType;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Memo1.Clear;
Memo1.Lines.Add(TA.Fn1(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">哈哈哈</span><span style="color: rgba(128, 0, 0, 1)">'</span>));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">接口调用</span>
TA.Proc2;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">接口调用</span>
<span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">end</span>.</pre>
</div>
<p>&nbsp;</p>
<p><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221204145409937-1677648729.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;<strong>接口属性:</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">此接口声明了一个 Name 属性; 因为接口没有字段, read/write 都只能从方法</span><span style="color: rgba(0, 128, 0, 1)">}</span><span style="color: rgba(0, 0, 0, 1)">
IMyInterface </span>= <span style="color: rgba(0, 0, 255, 1)">interface</span>
    <span style="color: rgba(0, 0, 255, 1)">function</span> GetName : <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">procedure</span> SetName(val : <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">);
    </span><span style="color: rgba(0, 0, 255, 1)">property</span> Name : <span style="color: rgba(0, 0, 255, 1)">string</span> <span style="color: rgba(0, 0, 255, 1)">read</span> GetName <span style="color: rgba(0, 0, 255, 1)">write</span><span style="color: rgba(0, 0, 0, 1)"> SetName;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">类实现的是接口的读写方法, 属性还是属于接口的; 类可以提供一个储存属性的字段</span><span style="color: rgba(0, 128, 0, 1)">}</span><span style="color: rgba(0, 0, 0, 1)">
TMyClass </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TInterfacedObject, IMyInterface)
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)">
    FName: </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
    <span style="color: rgba(0, 0, 255, 1)">function</span> GetName: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">procedure</span> SetName(val: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>&nbsp;<strong>接口可以被多次调用.因为接口的方法是抽象的,实体部分要到调用接口的类里面才具现,所以类调用接口的方法时,方法能执行什么功能,还不是你说的算?</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">type<br>  //接口</span><span style="color: rgba(0, 0, 0, 1)">
IMyInterface1 </span>= <span style="color: rgba(0, 0, 255, 1)">interface</span>
    <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Func(a,b: Integer): Integer;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
//调用接口的类1,这里的方法执行的是加法
TAdd </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TInterfacedObject, IMyInterface1)
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
    <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Func(a: Integer; b: Integer): Integer;  //Result:= a+b;
    </span><span style="color: rgba(0, 0, 255, 1)">destructor</span> <span style="color: rgba(0, 0, 255, 1)">Destroy</span>; <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
//调用接口的类2<span style="color: rgba(0, 0, 0, 1)">,这里的方法执行的是乘法</span>
TMul </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TInterfacedObject, IMyInterface1)
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
    <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Func(a: Integer; b: Integer): Integer;  <span style="color: rgba(0, 0, 0, 1)">//Result:= a*b;</span>
    </span><span style="color: rgba(0, 0, 255, 1)">destructor</span> <span style="color: rgba(0, 0, 255, 1)">Destroy</span>; <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>&nbsp; <strong>弱化引用使变量的接口计数器不被修改.</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">type<span style="color: rgba(0, 0, 0, 1)">
TForm1 = <span style="color: rgba(0, 0, 255, 1)">class<span style="color: rgba(0, 0, 0, 1)">(TForm)
    Memo1: TMemo;
    Button1: TButton;
    <span style="color: rgba(0, 0, 255, 1)">procedure<span style="color: rgba(0, 0, 0, 1)"> Button1Click(Sender: TObject);
<span style="color: rgba(0, 0, 255, 1)">private
    <span style="color: rgba(0, 128, 0, 1)">{<span style="color: rgba(0, 128, 0, 1)"> Private declarations <span style="color: rgba(0, 128, 0, 1)">}
<span style="color: rgba(0, 0, 255, 1)">public
    <span style="color: rgba(0, 128, 0, 1)">{<span style="color: rgba(0, 128, 0, 1)"> Public declarations <span style="color: rgba(0, 128, 0, 1)">}
<span style="color: rgba(0, 0, 255, 1)">end<span style="color: rgba(0, 0, 0, 1)">;

IFace = <span style="color: rgba(0, 0, 255, 1)">interface
    <span style="color: rgba(0, 0, 255, 1)">procedure<span style="color: rgba(0, 0, 0, 1)"> test;
<span style="color: rgba(0, 0, 255, 1)">end<span style="color: rgba(0, 0, 0, 1)">;

Ttype = <span style="color: rgba(0, 0, 255, 1)">class<span style="color: rgba(0, 0, 0, 1)">(TInterfacedObject, IFace)
    <span style="color: rgba(0, 0, 255, 1)">destructor <span style="color: rgba(0, 0, 255, 1)">Destroy; <span style="color: rgba(0, 0, 255, 1)">override<span style="color: rgba(0, 0, 0, 1)">;
    <span style="color: rgba(0, 0, 255, 1)">procedure<span style="color: rgba(0, 0, 0, 1)"> test;
<span style="color: rgba(0, 0, 255, 1)">end<span style="color: rgba(0, 0, 0, 1)">;

<span style="color: rgba(0, 0, 255, 1)">var<span style="color: rgba(0, 0, 0, 1)">
Form1: TForm1;

<span style="color: rgba(0, 0, 255, 1)">implementation

<span style="color: rgba(0, 128, 0, 1)">{<span style="color: rgba(0, 128, 0, 1)">$R *.dfm<span style="color: rgba(0, 128, 0, 1)">}

<span style="color: rgba(0, 128, 0, 1)">{<span style="color: rgba(0, 128, 0, 1)"> Ttype <span style="color: rgba(0, 128, 0, 1)">}

<span style="color: rgba(0, 0, 255, 1)">destructor Ttype.<span style="color: rgba(0, 0, 255, 1)">Destroy<span style="color: rgba(0, 0, 0, 1)">;
<span style="color: rgba(0, 0, 255, 1)">begin<span style="color: rgba(0, 0, 0, 1)">
Form1.Memo1.Lines.Add(<span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(128, 0, 0, 1)">Destroy<span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(0, 0, 0, 1)">);  //在实体中调用控件的话,要加上完整的对象位置.
<span style="color: rgba(0, 0, 255, 1)">inherited<span style="color: rgba(0, 0, 0, 1)">;
<span style="color: rgba(0, 0, 255, 1)">end<span style="color: rgba(0, 0, 0, 1)">;

<span style="color: rgba(0, 0, 255, 1)">procedure<span style="color: rgba(0, 0, 0, 1)"> Ttype.test;
<span style="color: rgba(0, 0, 255, 1)">begin<span style="color: rgba(0, 0, 0, 1)">
Form1.Memo1.Lines.Add(<span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(128, 0, 0, 1)">test<span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(0, 0, 0, 1)">);
<span style="color: rgba(0, 0, 255, 1)">end;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<p>调用:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">procedure<span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
<span style="color: rgba(0, 0, 255, 1)">var
<span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)">
<span style="color: rgba(0, 0, 0, 1)">a: IFace;
<span style="color: rgba(0, 0, 255, 1)">begin<span style="color: rgba(0, 0, 0, 1)">
   a:=Ttype.<span style="color: rgba(0, 0, 255, 1)">Create<span style="color: rgba(0, 0, 0, 1)"> ;
   a.test ;
   Form1.Memo1.Lines.Add(<span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(128, 0, 0, 1)">---<span style="color: rgba(128, 0, 0, 1)">'<span style="color: rgba(0, 0, 0, 1)">)
<span style="color: rgba(0, 0, 255, 1)">end;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></pre>
</div>
<p>&nbsp;<strong>可以看到,在不使用 weak 弱化引用时,程序正常执行.<br></strong></p>
<p><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221205131221503-152656714.png"> </p>
<p>&nbsp;<strong>如果把 <span style="color: rgba(0, 128, 0, 1)"> <span style="color: rgba(0, 0, 0, 1)">解除注释,则会出现内存错误.因为当a被创建时,因为weak的原因,a的接口计数器没有被加1,仍然等于0,所以系统就自动执行了destroy解析函数,把a给翻译掉了.当再执行a.test时,因为对象已经不存在,所以就会内存报错</span></span></strong></p>
<p>
<span style="color: rgba(0, 128, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221205131453234-539900176.png"></span></span></p>
<p><strong>&nbsp;和不同,它不会主动去清除接口计数器,它是憜性的,下面的例子还是延用上面的代码,可以看到Destroy程序并没有被执行</strong></p>
<p><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221205134408131-1061969747.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>再看一个网上的例子:</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
TA</span>=<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TInterfacedObject)

</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
a:IInterface;
<span style="color: rgba(255, 0, 0, 1)"></span>aweak:IInterface;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
a:</span>=TA.<span style="color: rgba(0, 0, 255, 1)">Create</span>;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">创建对象,复制给a,执行完成后引用计数器=1</span>
aweak:=a;       <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">由于aweak定义有属性,所以赋值给aweak后,引用计数器依旧为1,但aweak变量的地址被保存到一个weak关联列表中</span>
Memo1.Lines.Add(Format(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Ptr:%d</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, ));
a:</span>=<span style="color: rgba(0, 0, 255, 1)">nil</span>;         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">由于引用计数器=1,执行此句后,计数器清0,对象被释放,同时与此对weak关联列表中所有变量也被赋值为nil,包括aweak变量.</span>
Memo1.Lines.Add(Format(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Ptr:%d</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, ));
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>&nbsp;运行结果:<br>Ptr:16360080<br>Ptr:0<br><strong>weak引用非常适合用于两个对象需要互相引用的情况下,如果以往的引用,将无法让引用计数器清0.</strong></p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">&nbsp;方法别名:</span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>IFace = <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)">
    [</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">{3BA60C4E-CA74-489C-B74B-3FA791BC2843}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">]
    </span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> Ptest;
    </span><span style="color: rgba(255, 0, 0, 1)">function Ftest: string;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

IFace2 </span>= <span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)">
[</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">{324AB107-95F1-4145-B392-2E6F555822E3}</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">]
    </span><span style="color: rgba(255, 0, 0, 1)">function Ftest: string;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

Ttype </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TInterfacedObject, IFace, IFace2)
    </span><span style="color: rgba(0, 0, 255, 1)">destructor</span> <span style="color: rgba(0, 0, 255, 1)">Destroy</span>; <span style="color: rgba(0, 0, 255, 1)">override</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> Ptest;
    </span><span style="color: rgba(255, 0, 0, 1)">function F1: string;
    function F2: string;
    function IFace.Ftest = F1;
    function IFace2.Ftest = F2;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>&nbsp;</p>
<p><span style="font-size: 16px"><strong><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0"><span class="fontstyle1"><span class="fontstyle0">但是我在调用时,调不出F1和F2,不知道问题在哪里,在两个群问了半天,也没有等来答案,如果有大佬知道答案,麻烦指点一下,谢谢啦<br></span></span></span></span></span></span></span></span></span></span></span></span></span></span></strong></span></p>
<p>&nbsp;</p>
<p>&nbsp;<img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221205163243907-1654476776.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;<span style="font-size: 16px"><strong>P366-392 类操作</strong></span></p>
<p><span style="font-size: 16px"><strong>  1.类方法与类函数.</strong></span></p>
<p><span style="font-size: 16px"><strong>    在类里面声明的过程或者函数,只要在前面加上关键字class,就会变成类方法或者类函数.</strong></span>     </p>
<p><span style="font-size: 15px"><strong>       类方法不能在 private 和 protected 区;
&nbsp; </strong></span></p>
<p><span style="font-size: 15px"><strong>    类方法不能是虚方法; <br></strong></span></p>



<span style="font-size: 15px"><strong>    类方法只能使用类中的、在对象实例化以前的数据.</strong></span>
<p><span style="font-size: 15px"><strong>    类方法中包含一个隐藏参数self,它是指向类本身的一个参数</strong></span> </p>
<p><span style="font-size: 15px"><strong>    字段不能定义在published区域.在没有任何修饰符的情况下,默认就是<span style="font-size: 15px"><strong>published</strong></span>.</strong></span></p>
<div class="cnblogs_code">
<pre>Ttest = <span style="color: rgba(0, 0, 255, 1)">class</span>
<span style="color: rgba(0, 0, 255, 1)">private</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
      i: Integer;
      </span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
      n: Integer;
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
    <span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
      j: Integer;
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
      k: Integer;
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> Ptest;
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Ftest(o: integer): Integer;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;<br>---------------------------------<br></span><span style="color: rgba(0, 128, 0, 1)">{<span style="color: rgba(0, 128, 0, 1)"> Ttest <span style="color: rgba(0, 128, 0, 1)">}

<span style="color: rgba(0, 0, 255, 1)">class <span style="color: rgba(0, 0, 255, 1)">function<span style="color: rgba(0, 0, 0, 1)"> Ttest.Ftest(o: integer): Integer;
<span style="color: rgba(0, 0, 255, 1)">begin<span style="color: rgba(0, 0, 0, 1)">
Result := o * <span style="color: rgba(128, 0, 128, 1)">5<span style="color: rgba(0, 0, 0, 1)">;
<span style="color: rgba(0, 0, 255, 1)">end<span style="color: rgba(0, 0, 0, 1)">;

<span style="color: rgba(0, 0, 255, 1)">class <span style="color: rgba(0, 0, 255, 1)">procedure<span style="color: rgba(0, 0, 0, 1)"> Ttest.Ptest;
<span style="color: rgba(0, 0, 255, 1)">begin<span style="color: rgba(0, 0, 0, 1)">
i := k * <span style="color: rgba(128, 0, 128, 1)">2<span style="color: rgba(0, 0, 0, 1)">;
ShowMessage(i.ToString);<br> ShowMessage(Self.ClassName);
<span style="color: rgba(0, 0, 255, 1)">end;</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span style="color: rgba(0, 0, 0, 1)"><br></span>//调用
<span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Ttest.i :</span>= <span style="color: rgba(128, 0, 128, 1)">100</span>;    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">i=100</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">Ttest.n := 100;//ERROR,需要create</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)">Ttest.j := 100;   // ERROR,需要create</span>
Ttest.k := <span style="color: rgba(128, 0, 128, 1)">100</span>;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">k=100</span>
Ttest.Ptest;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">show 200(K*2) show Ttest</span>
ShowMessage(ttest.Ftest(<span style="color: rgba(128, 0, 128, 1)">10</span>).ToString);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">show 50(10*5) </span>
<strong><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;</span></strong></pre>
</div>
<p><strong>上面的代码中,从头到尾都没有对TTest进行create过,但是对于在定义阶段有加class的方法和字段,跟全局变量一样都是可以直接拿来使用的.相反,没加class的字段,在直接使用时全部都出现了异常.因为他们都需要创建实例后才能正常使用.</strong></p>
<span style="color: rgba(255, 0, 0, 1)"><strong>警告:使用没有经过初始化(赋值)的字段会抛出异常错误!</strong></span>
<p>&nbsp;</p>
<br>
<p><strong>类方法就是通过类名就可以访问的方法.或者你可以把它理解为命名空间也行.因为全局变量不被提倡,放到类里面就很好处理了,因为类里面有private,&nbsp; strict private ,public ,published ,protected等各种保护限制.当你要调用这些类方法或者类函数时,你得这么写: 类名.类方法,或者 类名 .类函数,这样就达到命名空间的效果.</strong></p>
<p><strong>调用时,这个类<span style="color: rgba(255, 0, 0, 1)">可以完全不用create</span>而直接使用它内部的类方法与类函数:</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
MyType: TMyType;
str: </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
MyType.Ptest;
str :</span>=<span style="color: rgba(0, 0, 0, 1)"> MyType.F1;<br>MyType.Destroy;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p><strong>  2.类的静态方法</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">现在的 Delphi 不仅仅有类方法, 同时有:
类变量: class var
类常量: class const
类类型: class type
类属性: class property

静态类方法就是给类属性来调用的, 它可以存在于私有区(private),
譬如下面的 SetName 就是一个静态类方法:
</span><span style="color: rgba(0, 128, 0, 1)">}</span><span style="color: rgba(0, 0, 0, 1)">
TMyClass </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">(TObject)
</span><span style="color: rgba(0, 0, 255, 1)">private</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">var</span> FName: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
   </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">procedure</span> SetName(<span style="color: rgba(0, 0, 255, 1)">const</span> Value: <span style="color: rgba(0, 0, 255, 1)">string</span>); static; <span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">静态类方法又多了一个 static 指示字</span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">published</span>
 <span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">property</span> Name: <span style="color: rgba(0, 0, 255, 1)">string</span> <span style="color: rgba(0, 0, 255, 1)">read</span> FName <span style="color: rgba(0, 0, 255, 1)">write</span><span style="color: rgba(0, 0, 0, 1)"> SetName;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p><strong>&nbsp;静态类方法相比类方法</strong></p>
<p><strong>  1.静态方法多了一个关键字,就是在定义的末尾加上了Static.</strong></p>
<p><strong>  2.静态方法没有隐藏的self参数,可以被当作callBack函数传给Windows API函数.</strong></p>
<p><strong>静态方法的调用约定: </strong></p>
<p>  <strong>只要记住Windows API参数调用是从右往左,D的调用方式跟他是想反的.</strong></p>
<p><strong>  凡是在D里面调用<strong>Windows API</strong>函数的,肯定要加 static;stdcall ; 进行转化<br></strong></p>
<p><strong>  </strong></p>
<p>  下面这一段转自https://blog.csdn.net/aaa000830/article/details/79986275 </p>
<p><strong>-----------------------------------------------------------------------------------------------------------------------</strong></p>
<p style="margin-bottom: 5px; border: 0; list-style: none; line-height: 21px; color: rgba(50, 62, 50, 1); font-family: simsun; text-align: left"><span style="color: rgba(255, 0, 0, 1)"><strong><span style="line-height: 21px"><span style="font-size: 16px">注: 使用错误,或者在该加的地方没有加,可能会出现"privileged instruction"错误,或者地址访问错误。</span></span></strong></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong><span style="font-size: 16px">常见的调用惯例有register,&nbsp;pascal,&nbsp;cdecl,&nbsp;stdcall,&nbsp;safecall。函数的调用管理决定了参数如何传递给子过程,并从堆栈中退出,以及寄存器在参数传递中的使用,错误和异常的处理。<span style="color: rgba(255, 0, 0, 1)">Delphi中默认的调用惯例是register。</span><br>  1) register和pascal:参数从左向右传递,也就是说最左边的参数最先求值并传入,最右边的参数最后求值和传入。cdecl,stdcall和safecall则按从右向左方向。<br>  2) 对于除cdecl之外的所有调用惯例,函数/过程在返回的时候要把堆栈中的参数退栈。对cdecl惯例,调用者在被调用的过程返回后执行参数退栈操作<br>  3) register调用惯例最多能用3个CPU寄存器来传递参数,而其它调用惯例只能通过堆栈来传递参数<br>  4) safecall调用惯例实现了异常的防火墙。在Windows上实现了跨进程的COM错误通知机制。<br>  5) register调用效率最高,因为它避免了堆栈的创建。<span style="color: rgba(255, 0, 0, 1)">Delphi中published属性必须是register。</span><br>  6) cdecl常用于调用C/C++编写的共享库中的函数;但是,如果要调用外部代码,那么一般要用stdcall和safecall<br>  7)&nbsp;<span style="line-height: 21px">在Windows上,系统的API都是stdcall和safecall;在其它操作系统上通常用cdecl(注意:stdcall比cdecl效率要高)<br>  8) 在dual-interface(双接口)方法中必须用safecall惯例。<br>  9) pascal惯例是为了向后兼容;near/far/export用于16位Window编程中的函数调用,在32位的应用程序中不发挥作用,仅仅是为了向后兼容。</span></span></strong></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong><span style="font-size: 16px"><span style="line-height: 21px">  10)即使静态方法只有一个参数,也要标明调用约定,因为不同的方式,汇编会最后给你弄不同的返回方式.<br>下表进行了总结:<br>Calling&nbsp;conventions Parameter&nbsp;order Clean-up Passes&nbsp;parameters&nbsp;in&nbsp;registers?<br>register Left-to-right Routine Yes<br>pascal Left-to-right Routine No<br>cdecl Right-to-left Caller No<br>stdcall Right-to-left Routine No<br>safecall Right-to-left Routine No</span></span></strong></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong><span style="font-size: 16px"><span style="line-height: 21px">--------------------转载结束-----------------------------------------</span></span></strong></span></p>
<p><span style="font-size: 16px"><strong>&nbsp;静态类的属性(class property):</strong></span></p>
<div class="cnblogs_code">
<pre>Ttest = <span style="color: rgba(0, 0, 255, 1)">class</span>
<span style="color: rgba(0, 0, 255, 1)">private</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
      FMyName: </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">function</span> GetMyName: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">; static;
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">procedure</span> SetMyName(Value: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">); static;<br>  //下面这两种方法是等价的,二选一
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">property</span> MyName: <span style="color: rgba(0, 0, 255, 1)">string</span> <span style="color: rgba(0, 0, 255, 1)">read</span> GetMyName <span style="color: rgba(0, 0, 255, 1)">write</span><span style="color: rgba(0, 0, 0, 1)"> SetMyName;
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">property</span> DirectName: <span style="color: rgba(0, 0, 255, 1)">string</span> <span style="color: rgba(0, 0, 255, 1)">read</span> FMyName <span style="color: rgba(0, 0, 255, 1)">write</span><span style="color: rgba(0, 0, 0, 1)"> FMyName;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
Form1: TForm1;

</span><span style="color: rgba(0, 0, 255, 1)">implementation</span>

<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$R *.dfm</span><span style="color: rgba(0, 128, 0, 1)">}</span>

<span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Ttest.SetMyName(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">张飞</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
ShowMessage(Ttest.FMyName);  //show 张飞
ShowMessage(Ttest.GetMyName);  //show 张飞
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;<br>
</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> Ttest </span><span style="color: rgba(0, 128, 0, 1)">}</span>
<span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">function</span> Ttest.GetMyName: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> fmyname;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">procedure</span> Ttest.SetMyName(Value: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
fmyname :</span>=<span style="color: rgba(0, 0, 0, 1)"> Value;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p><strong>这是说一下class var 与 var的区别.var是用来与class var做区分的,算了,我文笔不太好,还是用代码来说明吧</strong></p>
<p><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221208095837959-1767355557.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221208100018086-835397049.png"></p>
<p>&nbsp;<strong>还有一种方法,就是把calss var变量写在限制区域的最后面,这样就不会影响到其他字段了,比如</strong></p>
<p><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221208090637019-1560172955.png"></p>
<p><strong>类的构建函数与解析函数.</strong></p>
<p>  <strong>构建/解析函数优先级大于单元文件初始区(iniialization)与单元结束区(finalization).</strong></p>
<p><strong>  我们可以通过constructor和destructor关键字创建多个构建/解析函数,却不能使用class创建第二个类构建/类解析函数</strong></p>
<p><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221208101651020-1510675830.png"></p>
<p>&nbsp;</p>
<p>  <strong>单例模式&nbsp; (Singleton Pattern)</strong></p>
<p><strong>Singleton Pattern模式的设计意图是:保证一个类仅有一个实例,并提供一个访问他的全局访问点。单例模式在应用开发中比较常见,如 Application 或 Logger。在面试考试中出现率很高,别看书上一面带过,实际上还是有点复杂的,可以在B站上面搜索看看.</strong></p>
<p><strong>在 Delphi 的以前版本中,实现单例模式比较“另类”,自从 Delphi 后期加入一些新的语法元素后,单例模式的实现显得更为标准,和 C++、Java 中的实现方法几乎一致,最主要原因就是 Delphi 加入了类变量的支持,关键字为”class var”。<br>Delphi 同时支持类属性,可以让单例的访问更为友好;同时需要注意,在实现单例模式时,<span style="color: rgba(255, 0, 0, 1)">一定不要忘记把类本身的 Create 构建函数隐藏</span>,否则的话,单例的实现将没有意义。<strong><br>下面的代码实现了单例模式的 TLogger:</strong></strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
TLogger </span>= <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ( TObject )
</span><span style="color: rgba(0, 0, 255, 1)">private</span>
    <span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
      FInstance: TLogger;
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> GetInstance: TLogger; static;
</span><span style="color: rgba(0, 0, 255, 1)">protected</span>
    <span style="color: rgba(0, 0, 255, 1)">constructor</span> <span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
   <span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> Login;
    </span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> Logout;
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> ReleaseInstance;
    </span><span style="color: rgba(0, 0, 255, 1)">class</span> <span style="color: rgba(0, 0, 255, 1)">property</span> Instance: TLogger <span style="color: rgba(0, 0, 255, 1)">read</span><span style="color: rgba(0, 0, 0, 1)"> GetInstance;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>; </pre>
</div>
<p>Delphi Class of 类引用</p>
<p>以下内容转自http://t.zoukankan.com/yzryc-p-6396164.html</p>
<p><strong>Delphi Class of 类引用也就是类的类型,也可说是指向类的指针</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">Type
    TControlCls </span>= Class <span style="color: rgba(0, 0, 255, 1)">of</span><span style="color: rgba(0, 0, 0, 1)"> TControl;
    </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> CreateComponent(ControlCls: TControlCls): TControl;
    </span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
      result:</span>=ControlCls.<span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">(Form1);
      ...
    </span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p><strong>前者要求传入一个类, 而后者要求传入一个对象(类的实例)</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
MyClassRef</span>=calss <span style="color: rgba(0, 0, 255, 1)">of</span> CMyClass <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">表示MyClassRef为指向CMyClass或其父类的指针</span></pre>
</div>
<p><strong>类的引用就像指向类的指针一样</strong><br><strong>类引用就是类的类型,可以声明一个类引用变量赋给它一个类,可以通过这个变量创建对象的实例。</strong></p>
<p><strong>类的类,</strong><strong>当你不确定调用的类模型时候用到类的类。</strong><strong>也可以说是类指针~</strong></p>
<p><strong>System单元的TObject有如下方法:</strong><br><strong>function ClassType: TClass;</strong></p>
<p><strong>它就是获取对象的类类型,它的返回类型TClass就是class of TObject。</strong></p>
<p><strong>因为所有类都派生自TObject,所以所有对象都可以调用ClassType。比如:</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
S: TStringList;
C: TClass;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
S :</span>= TStringList.<span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">;
C :</span>=<span style="color: rgba(0, 0, 0, 1)"> S.ClassType;
ShowMessage(C.ClassName);</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对话框会显示出来TStringList,相当于TStringList.ClassName</span><span style="color: rgba(0, 0, 0, 1)">
S.Free
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<strong>而C.ClassName调用的是TObject的类方法ClassName,</strong>
<p><strong>原型:class function ClassName: ShortString;</strong></p>
<p><strong>就是说不需要用实例化的对象去调用,直接用类去调用就行了;不过用对象调用也是可以的,因为对象空间也保存了类的VMT地址。 </strong></p>
<p><strong>用类调用形如:TStringList.ClassName</strong><br><strong>用对象调用形如:S.ClassName</strong></p>
<p>&nbsp;</p>
<p>一个有意思的语法 :</p>
<h3><strong>class help for&nbsp; 类助手(我不知道该叫什么,书上译为类别助手), 对现有的类进行扩展,如果把类理解为一个容器,那么这条语法的作用是对现有的类的容器的成员进行扩展或者修改。</strong></h3>
<div class="cnblogs_code">
<pre>TTest = <span style="color: rgba(0, 0, 255, 1)">class    <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 0, 1)">//主类,正常定义</span></span></span></span>
<span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)">
    Fnumber: Integer;
    FText: </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)">
    FText2: </span><span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> increase;
    </span><span style="color: rgba(0, 0, 255, 1)">constructor</span> <span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

TTestHelp </span>= <span style="color: rgba(0, 0, 255, 1)">class</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> TTest    <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 0, 1)">//类助手,关键字为class Helper for后面跟主类名</span></span></span>
</span><span style="color: rgba(0, 0, 255, 1)">private</span>
    <span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> Show;  <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 0, 1)">//可以扩充主类的属性和方法</span></span></span>
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
    <span style="color: rgba(0, 0, 255, 1)">procedure</span> increase;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">将会覆盖掉原有的属性</span>
    <span style="color: rgba(0, 0, 255, 1)">function</span> test(): <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;  <span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 0, 1)">//可以扩充主类的属性和方法</span></span>
    </span><span style="color: rgba(0, 0, 255, 1)">constructor</span> <span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">(); <span style="color: rgba(0, 128, 0, 1)">//<span style="color: rgba(0, 128, 0, 1)">将会覆盖掉原有的方法</span></span>
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
Form1: TForm1;

</span><span style="color: rgba(0, 0, 255, 1)">implementation</span>

<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)">$R *.dfm</span><span style="color: rgba(0, 128, 0, 1)">}</span>

<span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> ttest </span><span style="color: rgba(0, 128, 0, 1)">}</span>

<span style="color: rgba(0, 0, 255, 1)">constructor</span> TTest.<span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">();  
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">inherited</span><span style="color: rgba(0, 0, 0, 1)">;
Fnumber :</span>= <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">;
FText :</span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">123</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
FText2 :</span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TTest.Create</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
Form1.Memo1.Lines.add(FText2);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TTest.increase;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Inc(Fnumber);
Form1.Memo1.Lines.add(Fnumber.ToString);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">{</span><span style="color: rgba(0, 128, 0, 1)"> TTestHelp </span><span style="color: rgba(0, 128, 0, 1)">}</span>

<span style="color: rgba(0, 0, 255, 1)">constructor</span> TTestHelp.<span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 0, 255, 1)">begin</span>
<span style="color: rgba(0, 0, 255, 1)">inherited</span><span style="color: rgba(0, 0, 0, 1)">;
Fnumber :</span>= <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">;
FText :</span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">abc</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
FText2 :</span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TTestHelp.Create</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
Form1.Memo1.Lines.add(FText2);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TTestHelp.increase;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Dec(Fnumber);
Form1.Memo1.Lines.add(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)"> TTestHelp.increase:</span><span style="color: rgba(128, 0, 0, 1)">'</span> +<span style="color: rgba(0, 0, 0, 1)"> Fnumber.ToString);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TTestHelp.Show;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Form1.Memo1.Lines.add(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TTestHelp.Show</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">function</span> TTestHelp.test(): <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Result :</span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">TTestHelp.test</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
Form1.Memo1.Lines.add(Result);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
<br>//调用
</span><span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
test: TTest;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
test :</span>= TTest.<span style="color: rgba(0, 0, 255, 1)">Create</span><span style="color: rgba(0, 0, 0, 1)">;  
test.show;
test.test();
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p><strong>输出如下:</strong></p>
<p><img src="https://img2023.cnblogs.com/blog/981841/202212/981841-20221210152837338-1343097019.png"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>概括一下类助手的特点:</strong></p>
<p><strong>  1.主类必须是<span style="color: rgba(255, 0, 0, 1)">已存在</span>的类,定义时也要注意先后顺序,先定义主类,再定义类助手,否则报错,这一点应该不难理解吧.</strong></p>
<p><strong>  2.类助手可以扩充主类的方法和属性.扩充的方法和属性可以是类方法,类变量与类属性,甚至还可以是虚拟方法!</strong></p>
<p><strong>  3.字段只能定义在主类中,类助手中不允许定义字段,否则会提报错: E2599 字段定义不允许在帮助器类型中</strong></p>
<p><strong>  4.主类和类助手是<span style="font-size: 18pt; color: rgba(255, 0, 0, 1)">一体的</span>,相当于把类助手的所有方法和属性都并到了主类里,同名即覆盖.</strong></p>
<p><strong>  包括构建函数和解析函数.也包括方法和属性的访问权限.比如主类里面是private,类助手是可以把它设置成public覆盖过去的.</strong></p>
<p><strong>  打个比方法,就像我们平时,把文件从A位置复制到B位置,然后中途弹出一个提示框,说存在同名文件,问你要不要覆盖,然后你选择了覆盖.</strong></p>
<p>  <strong>5.引用外部资源的类助手文件,必须在USES区域中加入.</strong></p>
<p><strong>  6.编译器只承认最后一个类助手.注意!这里不是覆盖啦!是忽视最后一个类助手之前的所有类助手!!只取最后一个类助手进行覆盖!!然后你是不是想套娃?比如给类助手再配个助手?  </strong></p>
<div class="cnblogs_code">
<pre> TTestHelp2 = <span style="color: rgba(0, 0, 255, 1)">class</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span> TTestHelp    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ERROR : E2021 需要class类型</span></pre>
</div>
<p><strong>  天真了吧!解决的方案之一是 真·套 "娃" ,这二是取别名(下面会讲)...重新定义一个类,让它继承原来的主类TTest,然后再给TTest2定义一个类助手,<span style="color: rgba(255, 0, 0, 1)">书中建议不要这么用,因为这会让类结构复杂化,源码难于解读.</span></strong></p>
<div class="cnblogs_code">
<pre>   TTest2=<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> (TTest )
   </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">something</span>
   <span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
TTestHelp2 </span>= <span style="color: rgba(0, 0, 255, 1)">class</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> TTest2
</span><span style="color: rgba(0, 0, 255, 1)">public</span>
    <span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> aaa;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>&nbsp;</p>
<p><strong>  7.类助手的意义在于<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">弥补主类功能上的不足</span></span></span>,而不是覆盖.覆盖会使人解读混乱.希望读者能明白这一点.用下面这个例子帮助大家理解:</strong></p>
<p><strong>我们通常取ListBox当前选中的值,都是</strong></p>
<div class="cnblogs_code">
<pre>ListBox1.Items </pre>
</div>
<p><strong>现在我觉得它使用起来太麻烦了,我需要按照我自己的方法来实现:</strong></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
TListboxHelper </span>= <span style="color: rgba(0, 0, 255, 1)">class</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> TListBox  //扩展
    </span><span style="color: rgba(0, 0, 255, 1)">function</span> ItemIndexValue: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">function</span> TListboxHelper.ItemIndexValue: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
Result :</span>= <span style="color: rgba(128, 0, 0, 1)">''</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> ItemIndex &gt;= <span style="color: rgba(128, 0, 128, 1)">0</span> <span style="color: rgba(0, 0, 255, 1)">then</span><span style="color: rgba(0, 0, 0, 1)">
    Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> Items ;
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;<br>//调用<br>str:= ListBox1.ItemIndexValue;</pre>
</div>
<p><strong>record helper for 与 class helper for相似,它是针对记录类型的.暂且叫它记录助手吧.<br></strong></p>
<p><strong>SysUils里的一些记录助手:</strong></p>
<div class="cnblogs_code">
<pre>TGUIDHelper = <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> TGUID
TStringHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">
TSingleHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Single
TDoubleHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Double
TExtendedHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Extended
TByteHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Byte
TShortIntHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> ShortInt
TWordHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Word
TSmallIntHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> SmallInt
TCardinalHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Cardinal
TIntegerHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Integer
TUInt64Helper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> UInt64
TInt64Helper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Int64
TNativeUIntHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> NativeUInt
TNativeIntHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> NativeInt
TBooleanHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> Boolean
TByteBoolHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> ByteBool
TWordBoolHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> WordBool
TLongBoolHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> LongBool
TCurrencyHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span> Currency <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> added in Delphi 11</span></pre>
</div>
<p>&nbsp;</p>
<p>类型助手:</p>
<p>  我们上面说过,编译器对于类助手与记录助手,只会识别最后一个助手,除了真套娃,还有其他方法吗?书上说:定义一个类型别名.类型别名会被编译器当成一个全新的类型,所以它可以拥有它自己的类助手.打个比方:银行规定一个人只能开一个账户(我们抛开银行开户的逻辑不谈),张三开了一个账户之后 ,又取了个小名叫张飞又开了一个账户,这样张三就有了两个账户了(助手).当张三想用第一个账户时,他就是张三,当他想用第二的账户时,他只需要转换一下身份,变成张飞就可以了.</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">type</span><span style="color: rgba(0, 0, 0, 1)">
MyInt </span>= <span style="color: rgba(0, 0, 255, 1)">type</span> Integer;  <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">要取别名,因为系统中已存在 TIntegerHelper = record helper for Integer</span>
<span style="color: rgba(0, 0, 0, 1)">
TMyIntHelper </span>= <span style="color: rgba(0, 0, 255, 1)">record</span> helper <span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> MyInt
    </span><span style="color: rgba(0, 0, 255, 1)">function</span> AsString: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 0, 255, 1)">function</span> MyIntHelper.AsString: <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
  Result :</span>=<span style="color: rgba(0, 0, 0, 1)"> IntToStr (self);
</span><span style="color: rgba(0, 0, 255, 1)">end</span><span style="color: rgba(0, 0, 0, 1)">;

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">调用</span>
<span style="color: rgba(0, 0, 255, 1)">procedure</span><span style="color: rgba(0, 0, 0, 1)"> TForm1.Button1Click(Sender: TObject);
</span><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">
MI: MyInt;
</span><span style="color: rgba(0, 0, 255, 1)">begin</span><span style="color: rgba(0, 0, 0, 1)">
MI :</span>= <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">;

Show (MI.AsString);

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Show (MI.toString); // this doesn't work </span>
<span style="color: rgba(0, 0, 0, 1)">Show (Integer(MI).ToString)
</span><span style="color: rgba(0, 0, 255, 1)">end</span>;</pre>
</div>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/yoooos/p/16949443.html
頁: [1]
查看完整版本: delphi D11编程语言手册 学习笔记(P344-392) 接口/类操作