Delphi - 当一个单元名称与属性名称相同时,如何解决冲突?

10
下面这个简单的例子是我试图解决一个冲突问题的概括,其中我有一个枚举类型成员与一个VCL成员同名。

下面这个简单的例子是我试图解决一个冲突问题的概括,其中我有一个枚举类型成员与一个VCL成员同名。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
    TSomeType = (
      alNone,
      alSome,
      alMany) ;

procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Align := alNone ;                    // 1.  type mismatch
Self.Align := Controls.alNone ;           // 2.  "Controls" is also a property of TForm
end ;

end.
  • 第一个任务失败是因为编译器认为alNone是我声明的变量,而不是在Controls.pas中定义的TAlign成员。
  • 第二个任务失败是因为它把Controls解释为同名的TForm属性。

我知道有办法解决这个问题(最简单的方法是重命名alNone成员),但我想知道是否有一种方法可以限定对另一个单位中属性的引用,在该作用域中存在与该单位名称冲突的标识符。

2个回答

10

在类型名称后面加上限定词:

TAlign.alNone

在我写这篇文章的时候,我没有意识到编译器版本的相关性。这种语法只在Delphi 2010或XE中才可用。因此,这个答案并不适合标记版本Delphi 2007。Deltics的回答涵盖了更多细节。


个人而言,我总是这样编写枚举类型。更有意义,也更常见(跨不同的语言)。 - Etsitpab Nioliv
@ross - 你是如何在D2007中实现的?我这边出现了错误:“[DCC Error] Unit1.pas(33): E2018 Record, object or class type required”。 - Sertac Akyuz
有趣的是,我确信语法始终可用,但你是完全正确的。 - David Heffernan
@Sertac - 我已经通过选择一个不冲突的名称来解决了这个问题,并且没有尝试使用类型名称进行限定。 - rossmcm

6
正如David的回答所建议的那样,对于枚举类型或其他情况,在类型可用于限定涉及标识符的情况下,您当然可以根据需要直接使用类型名称:
someAlign  := TAlign.alNone;
someMyType := TMyType.alNone;

这种使用枚举的方式被称为“作用域枚举”,不支持旧版本的Delphi编译器。我相信XE2可能是引入它的版本。当然,这个版本默认情况下强制执行以这种方式限定枚举。
尽管可以通过编译器指令关闭它。关闭后,您仍然可以使用作用域枚举,但不是必须的
在支持此功能的版本中,必须对任何定义的枚举进行限定,同时打开此功能。在使用关闭此功能时定义的枚举时,可以选择是否限定。
type
{$SCOPEDENUMS ON}
TFoo = (Black, White);  // MUST qualify:  eg. "TFoo.Black"

{$SCOPEDENUMS OFF}
TBar = (Black, White);  // MAY qualify or not if/as needed

对于不支持作用域枚举的旧版Delphi或标识符不是枚举成员且无法通过类型限定的情况 - 例如,如果您的标识符与某些单元级别的标识符(例如在Controls中的mrOk)冲突,则需要进行一些额外的工作,但并不多。

在这些情况下,只需定义一个新常量以创建另一个单元中常量的明确“本地别名”,并在单元名称不明确的地方引入它。类似于:

  type
    TMyResult = (
      mrOk,
      mrFailed) ;

  const
    Controls_mrOk = Controls.mrOk;  // mrOk is a const, not an enum member

XE允许TAlign.alNone,而2007不支持。文档可以追溯到2010年(http://docwiki.embarcadero.com/RADStudio/XE/e/index.php?title=Scoped_Enums_(Delphi)&action=history)。可能是XE或者2010。 - Sertac Akyuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接