0

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

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)或使用与我想忘记的字符串数量一样多的缓冲区变量?

有没有更优雅的方式?

谢谢。

4

3 回答 3

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');
于 2013-09-20T13:11:43.283 回答
0

在我看来,使用带有更多描述性变量的重载是最好的方法。我总是试图让意图揭示接口和名称

于 2013-09-20T12:37:01.977 回答
0

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

严格来说,这不是你在这里所做的。当然,事情正在被复制,但复制到变量,而不是对象。并且考虑到由于使用变量,引用参数会影响您指定默认值,我建议您将复制到整个对象的实际副本。

设计具有内置复制机制TPerson的类型类(由设计者实现/扩展)并使用默认参数扩展构造函数:TPersistent

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;
于 2013-09-20T17:05:35.633 回答