枚举类型和助手的可见性
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
一定是有效的。
- 您应该注意到与对象和记录相似。您始终可以引用 public 成员,即使您只引入 class/record 类型。
- 这与前面的情况不同,因为您使用了
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;
我有几个基本单元,需要分开放置,但为了便于使用,我想将它们组合成一个单元。现在我对枚举类型和助手有问题,不确定是否还有其他问题。有可能使这项工作吗?
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
一定是有效的。- 您应该注意到与对象和记录相似。您始终可以引用 public 成员,即使您只引入 class/record 类型。
- 这与前面的情况不同,因为您使用了
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;