Delphi 2010中记录与类的类方法

Moh*_*man 17 delphi delphi-2010

我刚刚开始使用Delphi 2010中的新单元IOUtils.pas,我发现它们将所有方法都放在Records(TFile, TPath, TDirectory)类函数和过程中.

在记录而不是类中执行此操作有什么好处吗?在这两种情况下都不需要任何变量或实例,但我不确定在内存消耗或性能改进方面是否有任何实际好处.

Uwe*_*abe 21

记录中的类方法用于将不同的方法分组到公共名称空间中.因此,您可以为不同的目的使用类似的命名方法.有关IOUtils.pas中的示例,请查看TFile和TDirectory中提供的Exists函数.较旧的方法是为FileExists和DirectoryExists(实现实际调用)具有不同的函数名称.

虽然类中的类方法可以以相同的方式使用,但它们还可以有另一个目标:它们可以是虚拟的.从类变量调用,这可能导致不同的实现,具体取决于该变量的当前内容.这不适用于记录.因此,记录中的类方法始终是静态的.

  • +1用于解释记录和类类型中类方法之间的真正区别. (4认同)
  • Pascal中的单位已经为"命名空间分组"目的服务.FileExists +目录存在不是一个"较旧"的目的,它只是一种区分功能的不同方式.它们可以很简单地在IOUtils.Files和IOUtils.Directories单元中使用简单的"存在"功能(但是请注意,点阵单元名称仅从D7开始支持 - 当然可以使用类似的非点缀区别,当然). (4认同)
  • 您可能还想提及受保护的成员可见性。 (2认同)

Del*_*ics 9

我想说的第一个问题是"为什么把这些函数放在记录类中?" 首先.

IOUtils中使用记录方法在很多情况下在Delphi中基本上是任意的,并且部分反映了在Delphi中与其他语言无关的具有以下约定的迷信.

在某些语言(Java和.NET?)中,不支持"第一类"功能.也就是说,程序和函数不能独立于任何容器类存在.因此,在这些语言中,如果您有函数和过程,则必须将它们包含在类中.如果它们不对成员数据进行操作,那么显然它们被声明为类方法,以避免仅仅为了调用实际上是classLESS函数而构造一个实例.

TDirectory.Exists(s)TFile.Exists(s)DirectoryExists(s)FileExists(s)的语法替代品.

在Delphi第一类函数支持,因此没有使用类或记录,功能区分,除非在编写代码时便于便于参考为开发和使用IDE援助,以浏览可用方法的方式没有真正的理由.

没有容器记录/类,您必须知道有一个名为" DirectoryExists() " 的函数.使用容器记录,您只需知道存在类型TDirectory,然后IDE(通过代码完成建议)可以呈现可用于TDirectory操作的所有"方法" .

但是,在Delphi中,通过支持一流功能可以实现另一种选择.您(或者更确切地说是IOUtils的作者)可以选择使用现有容器 - 一个Delphi"单元" ,而不是使用任意和人为的"容器":

  unit IOUtils.Directory;

  interface

  function Exists(s): Boolean;
Run Code Online (Sandbox Code Playgroud)

  unit IOUtils.File;

  interface

  function Exists(s): Boolean;
Run Code Online (Sandbox Code Playgroud)

这仍然以代码完成建议的形式享受IDE支持的好处,并且还提供了支持在不同事物上运行的相同功能名称所需的命名空间分离.

这种方法(它是一个大的)的缺点是,其中一个单元同时使用IOUtils.FileIOUtils.Directory,它必须符合一个或其他函数名,以避免混淆,但这种资格可能被省略,这是为什么它太危险了:

  uses
    IOUtils.File,
    IOUtils.Directory;
  ..
  begin
    if Exists(s) then  // << tests existence of a directory
    ..
    if IOUtils.File.Exists(s) then  // << ensure we test for a file
    ..
    if IOUtils.Directory.Exists(s) then  // << ensure we test for a directory
  end
Run Code Online (Sandbox Code Playgroud)

当然,这也可能是一个优势,如果您的单元包含仅适用于目录的代码,它将仅使用IOUtils.Directory,并且无需限定并在uses子句以外的任何地方重复该事实.

当然,潜在且非常真实的危险是,将来如果单元被扩展并随后开始使用IOUtils.File,那么这很容易导致任何不合格的引用上的作用域错误.

您在代码中偏好哪种方法在很大程度上取决于个人偏好以及在范围错误中发生冲突的可能性,其中您具有在不同实体上运行的类似/相同命名或语义上等效的函数.

出于这些原因,IOUtils中的设计选择至少是可以理解的,并且可以说是一个很好的选择,因为ymmv.

但在其他情况下,如果您正在寻找的是一种将相关函数分组的方法,这些函数不会出现与类似函数混淆/冲突的风险,那么使用人工和任意容器是多余的.函数必须驻留的单元本身可以提供您需要的所有分组行为.

至于为何记录而不是班级...

我怀疑在制作这些任意容器时使用记录而不是类可能会有一点静态内存的好处.我认为一个类有额外的开销,这本质上是相对较小和静态的(即每个类的开销稍微多一点,但与使用类方法的次数无关).


klu*_*udg 5

静态类方法只是一种语法糖 - 您始终可以将它们实现为普通过程/函数。

如果在记录内部实现类方法,则开销较小。任何类声明都需要一个额外的结构来存储内存中的类信息。记录没有结构。