我有一个项目有两个具有相同名称的表单。我需要使用其中一个。我假设我可以使用IFDEF来区分它们,但我发现在没有编译器抱怨的情况下我无法将它们都添加到项目中。我的使用条款看起来像这样。
uses
uFileManager, uMount, uSkyMap, uAntenna,
{$IFDEF SDR}
uSDR,
{$ENDIF}
{$IFDEF R7000Serial}
uR7000,
{$ENDIF}
uDatabase;
{$R *.dfm}
'uSDR'和'uR7000'单位都有一个名为'Receiver'的表格。当我尝试添加“uR7000”单元时,我得到了以下项目: “该项目已包含名为Receiver的表单或模块”
如何将两个单元添加到项目中?
答案 0 :(得分:5)
首先,不是编译器抱怨而是IDE。
编译器并不关心您是否具有相同名称的表单或其他类型,只要它们位于不同的单元中即可。 VCL的一个着名例子是两个 TBitmap 类型,一个在图形,另一个在 Windows 。如果你需要明确指出你的意思是什么类型,你只需要在代码中限定类型名称,编译器就会告诉你。
bmpA: Graphics.TBitmap; // bmpA is a TBitmap as defined in the Graphics unit
bmpB: Windows.TBitmap; // bmpB is a TBitmap as defined in the Windows unit
没问题。
然而,如果你有持久类具有相同的名称,那么Delphi 中的持久性框架会关注,因为持久性框架只识别类型他们的不合格的名称。
这就是Delphi的每个第三方组件框架在其类名上使用前缀的原因。这不仅仅是虚荣或时尚。如果两个库都在同一个项目中使用,它可以确保一个库中的组件(通过Delphi持久性机制)与另一个库中的另一个组件混淆。
底线:坚持使用表单的唯一名称,并根据需要找到其他方法来区分或切换它们。
如果没有关于您的项目的更多详细信息,很难建议如何管理您对哪个特定表单的使用的参考。您可以从公共基类派生,也可以为每个基类定义一个接口。
例如(这是只是一个说明性的草图,而不是推荐或完全工作的解决方案):
// Define the interface that your Receiver implementations
// must satisfy. This might include returning a reference to the implementing form.
//
// e.g. in a unit "uiReceiver"
type
IReceiver = interface
function Form: TForm; // returns the form using the common base type, not the specific implementation class
end;
// in unit uSDR
TfrmSDRReceiver = class(TForm, IReceiver)
..implements IReceiver as well as your SDR specific needs
end;
// in unit u7000
TfrmR7000SerialReceiver = class(TForm, IReceiver)
..implements IReceiver as well as your R7000 Serial specific needs
end;
// In uReceiver (some unit to "resolve" the receiver)
interface
uses
uSDR,
uR7000;
type
TReceiver = class
class function GetReceiver: IReceiver;
end;
implementation
class function TReceiver.GetReceiver: IReceiver;
begin
{$ifdef SDR}
result := frmSDRReceiver;
{$endif}
{$ifdef R7000}
result := frmR7000SerialReceiver;
{$endif}
end;
end.
您的应用程序代码然后使用 uReceiver 单元(如果您想引用接口类型,例如在变量声明中,则使用 uiReceiver )并访问特定的通过提供的静态类实现Receiver ,例如:
uses
uReceiver;
implementation
uses
uiReceiver;
..
var
rcvr: IReceiver;
begin
rcvr := TReceiver.GetReceiver;
rcvr.... // work with your receiver through the methods/properties on the interface
// You can also work with the receiver form, accessing all aspects
// common to any TForm via the Form function on the interface (assuming
// you chose to provide one):
rcvr.Form.Show;
..
end;