Delphi参考参数/默认参数

时间:2013-09-20 12:06:50

标签: delphi reference refactoring default-value

假设我有一个我想复制的对象。

interface

type
  TPerson = Class(TObject)
  public
    first_name: string;
    last_name: string;
    address: string;
  public
    constructor Create;
    procedure CopyTo(var s1, s2, s3: string);
  ...

implementation

...

procedure TPerson.CopyTo(var s1, s2, s3: string)
begin
  s1 := first_name;
  s2 := last_name;
  s3 := address;
end;

end.

然后我可以像这样使用我的课程:

...
var
  name1, name2, address: string;
begin
  person := TPerson.Create;
  person.first_name = 'John';
  person.last_name = 'Doe';
  person.address = '10 Downing Street';
  person.CopyTo(name1, name2, address);
end;

但如果我对复制地址不感兴趣,我希望能够像这样使用它

...
var
  name1, name2: string;
begin
  person := TPerson.Create;
  person.first_name = 'John';
  person.last_name = 'Doe';
  person.address = '10 Downing Street';
  person.CopyTo(name1, name2);

  // Some bad legacy code that has a lot more unstructured fields
end;

我在考虑编写一个重载CopyTo(var s1, s2: string)或者使用尽可能多的缓冲区变量作为我想忘记的字符串数量?

有更优雅的方式吗?

感谢。

3 个答案:

答案 0 :(得分:2)

您的问题标题表明您需要某种默认参数来表示您不想使用的参数。 Delphi不支持该功能。 (我也不知道任何其他语言。)你必须为你想要获得副本的每个字段组合编写单独的函数。它们可以是单个名称的重载,或者它们都可以具有指示它们返回哪些字段的名称;如果单独的类型不能区分您希望支持的所有组合,则可能需要单独的名称。

但在你这样做之前,退后一步考虑你的目标。您编写了一个将公共成员的值复制到变量中的函数。为什么这个功能需要存在?只需复制您需要的成员:

person.first_name = 'John';
person.last_name = 'Doe';
person.address = '10 Downing Street';
name1 := person.first_name;
name2 := person.last_name;

另一种方法是为您的类编写一个合适的构造函数,这样您就不必在已经创建它之后初始化它的所有字段。保留您想要的值的副本:

name1 := 'John';
name2 := 'Doe';
person := TPerson.Create(name1, name2, '10 Downing Street');

答案 1 :(得分:0)

在我看来,使用带有更多描述性变量的重载是最好的方法。 我总是尝试制作intention revealing interfaces和名字

答案 2 :(得分:0)

  

假设我有一个我想复制的对象。

严格地说,这不是你在这里做的。当然,事情正在被复制,但是变量,而不是对象。考虑到由于使用了变量标签而引用的参考参数让您无法指定默认值,我建议您复制到整个对象的实际副本

设计TPersonTPersistent类,它具有一种内置复制机制(由设计者实现/扩展),并使用默认参数扩展构造函数:

type
  TPerson = Class(TPersistent)
  private
    FFirstName: String;
    FLastName: String;
    FAddress: String;
  public
    procedure Assign(Source: TPersistent); override;
    constructor Create(AFirstName: String = ''; ALastName: String = '';
      AAddress: String = ''); overload;
    constructor Create(APerson: TPerson); overload;
    property FirstName: String read FFirstName write FFirstName;
    property LastName: String read FLastName write FLastName;
    property Address: String read FAddress write FAddress;
  end;

procedure TPerson.Assign(Source: TPersistent);
begin
  if Source is TPerson then
  begin
    FFirstName := TPerson(Source).FFirstName;
    FLastName := TPerson(Source).FLastName;
    FAddress := TPerson(Source).FAddress;
  end
  else
    inherited Assign(Source);
end;

constructor TPerson.Create(AFirstName, ALastName, AAddress: String);
begin
  inherited Create;
  FFirstName := AFirstName;
  FLastName := ALastName;
  FAddress := AAddress;
end;

constructor TPerson.Create(APerson: TPerson);
begin
  inherited Create;
  Assign(APerson);
end;

现在,您的可能性不同于:

procedure Example1;
var
  Person: TPerson;
  PersonCopy: TPerson;
begin
  Person := TPerson.Create;
  Person.FirstName := 'John';
  Person.LastName := 'Doe';
  Person.Address := '10 Downing Street';
  PersonCopy := TPerson.Create;
  PersonCopy.Assign(Person);
  //...
end;

为:

procedure Example2;
var
  Person: TPerson;
  PersonCopy: TPerson;
begin
  Person := TPerson.Create('John', 'Doe');
  PersonCopy := TPerson.Create(Person);
  //...
end;