假设我有一个我想复制的对象。
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)
或者使用尽可能多的缓冲区变量作为我想忘记的字符串数量?
有更优雅的方式吗?
感谢。
答案 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)
假设我有一个我想复制的对象。
严格地说,这不是你在这里做的。当然,事情正在被复制,但是变量,而不是对象。考虑到由于使用了变量标签而引用的参考参数让您无法指定默认值,我建议您复制到整个对象的实际副本。
设计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;