目前我正在将用VBA编写的项目转换为Delphi,并且偶然发现了使用Optional
参数转换一些Subs的问题。
比方说,有一个Sub声明(只是一个例子,实际的Subs有多达10个可选参数):
Sub SetMark
(x0 As Double, y0 As Double,
Optional TextOffset As Integer =5,
Optional TextBefore As String = "",
Optional Text As String = "",
Optional TextAfter As String = "mm",
Optional Color As String = "FFFFFF",
Optional ArrowPresent As Boolean = True)
随后可以这样调用Sub:
Call SetMark (15, 100,,,"135")
Call SetMark (100, 100, 8,, "My text here..", "")
'a lot of calls here
Optional
参数在这里非常灵活,您可以省略其中任何一个,并且您也可以为其中任何一个赋值。与德尔福不同。
Procedure SetMark
(x0: real; y0: real,
TextOffset: Integer =5;
TextBefore: ShortString = '';
Text: ShortString = '';
TextAfter: ShortString = 'mm';
Color: ShortString = 'FFFFFF';
ArrowPresent: Boolean = True);
看来你不能只复制VBA电话:
SetMark (15, 100,,,'135');// error here
所以,问题是:有没有办法将Subs转换为Delphi程序,保持参数的相同灵活性? 我的第一个想法是使用默认参数,但它不起作用。 至于现在,在Delphi中我似乎必须直接传递列表中的所有参数,但这意味着需要进行大量的工作来审查和正确移植VBA调用。
有什么想法吗?
答案 0 :(得分:12)
有没有办法将VBA子程序转换为Delphi程序,仍然保持参数的相同灵活性?
没有办法实现这一点 - 除了列表末尾之外,省略参数的灵活性根本不存在。
对于自动化对象的方法,您可以使用命名参数,如下所述:Named/optional parameters in Delphi?但是,我非常建议您不要将类实现为自动化对象,只是为了获得该功能。
每当您在语言之间切换时,您会发现不方便的差异。这是不可避免的。最好的方法是尝试找到解决新语言问题的最佳方法,而不是试图将旧语言中的习语强制为新语言。
在这种情况下,您可能希望使用overloaded functions或parameter objects作为缓解此不便的方法。
答案 1 :(得分:2)
为了扩展重构使用参数对象的想法,您可以声明如下记录:
TSetMarkParams = record
x0 : double;
y0 : double;
TextOffset : integer;
TextBefore : string;
Text : string;
TextAfter : string;
Color : string;
ArrowPresent : boolean;
constructor Create(Ax0, Ay0 : double);
end;
并实现构造函数以将默认值填充为:
constructor TSetMarkParams.Create(Ax0, Ay0 : double);
begin
x0 := Ax0;
y0 := Ay0;
TextOffset := 5;
TextBefore := '';
Text := '';
TextAfter := 'mm';
Color := 'FFFFFF';
AllowPresent := true;
end;
您的程序将有签名:
procedure SetMark(ASetMarkParams : TSetMarkParams);
然后,您可以使用SetMark (15, 100,,,'135');
调用的示例:
var
LSetMarkParams : TSetMarkParams
begin
LSetMarkParams := TSetMarkParams.Create(15, 100);
LSetMarkParams.Text := '135';
SetMark(LSetMarkParams);
end;
作为附带的好处,上面的内容更具可读性,因为它可以避免在返回调试麻烦的方法调用时盲目尝试计算逗号。