枚举类型和助手的可见性

Visibility of enumeration types and helpers

我有几个基本单元,需要分开放置,但为了便于使用,我想将它们组合成一个单元。现在我对枚举类型和助手有问题,不确定是否还有其他问题。有可能使这项工作吗?

BaseUnit

type
  TCustomEnum = (ceValue1, ceValue2, ceValue3);

TCustomEnumHelper = record helper for TCustomEnum
  function AsString: string;
end;

GroupUnit

uses BaseUnit;

TCustomEnum = BaseUnit.TCustomEnum; 

其他单位的用法。

uses GroupUnit;

procedure DoSomething;
var
  lValue : TCustomEnum;
begin
  lValue := ceValue1; // doesn't work
  lValue := TCustomEnum.ceValue1; // works 
  lValue.AsString; // doesn't work
end;

您的实验结果完全符合预期。

您的第三个单元可以访问 TCustomEnum 的唯一原因是 GroupUnit 使用相同的标识符 但仅使用该标识符 声明了类型别名。重要的是要注意,这是 Delphi 编译过程与 C++ 不同的重要方式。而 C++ 递归地将所有包含拉入编译范围,Delphi 仅拉入直接包含单元的 interface 部分。

  • lValue := ceValue1; 不起作用,因为 ceValue1 未在编译范围内定义。
  • lValue := TCustomEnum.ceValue1; 之所以有效,是因为 TCustomEnum 被完整地引入了。也就是说因为TCustomEnum等于BaseUnit.TCustomEnum:也就是说TCustomEnum.ceValue1一定是有效的。
    1. 您应该注意到与对象和记录相似。您始终可以引用 public 成员,即使您只引入 class/record 类型。
    2. 这与前面的情况不同,因为您使用了 ceValue1 而没有 any 资格。并且在范围内没有对该标识符的不合格定义。
  • lValue.AsString; 这不起作用,因为使 AsString 可用的助手不在范围内。

有些情况下声明类型别名会很有用。但我必须指出通用分组单元的想法存在严重缺陷。

是的,它确实减少了您必须 使用 以拉出 large1 的单位数量数量 的依赖项。 IE。您认为将 uses Unit1, Unit2, Unit3, Unit4, Unit5, Unit6; 替换为较短的 uses GroupUnit;.

是在节省时间

但是大1 依赖项意味着您还引入了不需要的东西。这导致:

  • 一个管理不善的体系结构,其中一切都间接依赖于几乎所有其他事物。 (也称为 "Big Ball Of Mud" 建议研究 。)
  • 不必要的间接级别;这意味着如果你想找到你正在使用的东西的定义,你 Find declaration... 只能找到别名,并且必须再次 Find declaration... 才能找到你真正想要的东西。

是的,列出您正在使用的每一件东西似乎需要更多工作。但是,如果您使用了太多令人沮丧的东西,您应该问问自己:为什么我的 class 如此复杂? 然后 我的设计有什么问题;我该如何改进它?


最后一点,您可以为枚举设置别名;只要您明确这样做。

以下可能就足够了(但还是要谨慎使用)。 尤其是因为工作量很大。

unit GroupUnit;

interface

uses BaseUnit;

type
  TCustomEnum = BaseUnit.TCustomEnum;
  TCustomEnumHelper = BaseUnit.TCustomEnumHelper;
const
  ceValue1 = BaseUnit.ceValue1;
  ceValue2 = BaseUnit.ceValue2;
  ceValue3 = BaseUnit.ceValue3;