在过程中将不同的记录类型作为参数传递?
Pass different record types as parameter in a procedure?
在过程中将不同类型的记录作为参数传递有技巧吗?例如,看看这个 伪代码 :
type
TPerson = record
Species: string;
CountLegs: Integer;
end;
TSpider = record
Species: string;
CountLegs: Integer;
Color: TColor;
end;
var
APerson: TPerson;
ASpider: TSpider;
// Is there a trick to pass different record types as parameter in a procedure?:
procedure DoSomethingWithARecord(const ARecord: TAbstractRecord?);
begin
if ARecord is TPerson then
DoSomethingWithThisPerson(ARecord as TPerson)
else if ARecord is TSpider then
DoSomethingWithThisSpider(ARecord as TSpider);
end;
procedure DefineRecords;
begin
APerson.Species := 'Human';
APerson.CountLegs := 2;
ASpider.Species := 'Insect';
ASpider.CountLegs := 8;
ASpider.Color := clBtnFace;
DoSomethingWithARecord(APerson);
DoSomethingWithARecord(ASpider);
end;
记录实例不像 类 那样包含类型信息。所以你需要传递一个额外的参数来表明你正在使用哪种类型。例如:
type
TRecordType = (rtPerson, rtSpider);
procedure DoSomething(RecordType: TRecordType; const ARecord);
begin
case RecordType of
rtPerson:
DoSomethingWithThisPerson(TPerson(ARecord));
rtSpider:
DoSomethingWithThisSpider(TSpider(ARecord));
end;
end;
您可能会考虑将类型代码放在每条记录的第一个字段中:
type
TPerson = record
RecordType: TRecordType;
Species: string;
CountLegs: Integer;
end;
TSpider = record
RecordType: TRecordType;
Species: string;
CountLegs: Integer;
Color: TColor;
end;
function GetRecordType(ARecord): TRecordType;
begin
Result := TRecordType(ARecord);
end;
....
procedure DoSomething(const ARecord);
begin
case GetRecordType(ARecord) of
rtPerson:
DoSomethingWithThisPerson(TPerson(ARecord));
rtSpider:
DoSomethingWithThisSpider(TSpider(ARecord));
end;
end;
您可以使用泛型:
type
TMyRecordDispatcher = record
class procedure DoSomething<T: record>(const Value: T); static;
end;
class procedure TMyRecordDispatcher.DoSomething<T>(const Value: T);
begin
if TypeInfo(T) = TypeInfo(TPerson) then
DoSomethingWithThisPerson(PPerson(@Value)^)
else if TypeInfo(T) = TypeInfo(TSpider) then
DoSomethingWithThisSpider(PSpider(@Value)^);
end;
并像这样调用函数:
TMyRecordDispatcher.DoSomething(APerson);
TMyRecordDispatcher.DoSomething(ASpider);
这使用泛型类型推断,因此您无需显式声明类型。尽管作为泛型的一个例子,它让我感到畏缩。请不要这样做。
在我看来,所有这些都是混乱而脆弱的。上面的大部分重新实现 运行 时间方法分派,多态性。 类 更适合这个。我不认可上面的任何代码。
另一方面,也许这一切都是不必要的。有什么问题:
DoSomethingWithThisPerson(Person);
DoSomethingWithThisSpider(Spider);
既然你在编译时就知道类型,为什么要选择更复杂的东西?
您可以使用函数重载来省略函数名中的类型。
procedure DoSomething(const APerson: TPerson); overload;
begin
....
end;
procedure DoSomething(const ASpider: TSpider); overload;
begin
....
end;
....
DoSomething(Person);
DoSomething(Spider);
在过程中将不同类型的记录作为参数传递有技巧吗?例如,看看这个 伪代码 :
type
TPerson = record
Species: string;
CountLegs: Integer;
end;
TSpider = record
Species: string;
CountLegs: Integer;
Color: TColor;
end;
var
APerson: TPerson;
ASpider: TSpider;
// Is there a trick to pass different record types as parameter in a procedure?:
procedure DoSomethingWithARecord(const ARecord: TAbstractRecord?);
begin
if ARecord is TPerson then
DoSomethingWithThisPerson(ARecord as TPerson)
else if ARecord is TSpider then
DoSomethingWithThisSpider(ARecord as TSpider);
end;
procedure DefineRecords;
begin
APerson.Species := 'Human';
APerson.CountLegs := 2;
ASpider.Species := 'Insect';
ASpider.CountLegs := 8;
ASpider.Color := clBtnFace;
DoSomethingWithARecord(APerson);
DoSomethingWithARecord(ASpider);
end;
记录实例不像 类 那样包含类型信息。所以你需要传递一个额外的参数来表明你正在使用哪种类型。例如:
type
TRecordType = (rtPerson, rtSpider);
procedure DoSomething(RecordType: TRecordType; const ARecord);
begin
case RecordType of
rtPerson:
DoSomethingWithThisPerson(TPerson(ARecord));
rtSpider:
DoSomethingWithThisSpider(TSpider(ARecord));
end;
end;
您可能会考虑将类型代码放在每条记录的第一个字段中:
type
TPerson = record
RecordType: TRecordType;
Species: string;
CountLegs: Integer;
end;
TSpider = record
RecordType: TRecordType;
Species: string;
CountLegs: Integer;
Color: TColor;
end;
function GetRecordType(ARecord): TRecordType;
begin
Result := TRecordType(ARecord);
end;
....
procedure DoSomething(const ARecord);
begin
case GetRecordType(ARecord) of
rtPerson:
DoSomethingWithThisPerson(TPerson(ARecord));
rtSpider:
DoSomethingWithThisSpider(TSpider(ARecord));
end;
end;
您可以使用泛型:
type
TMyRecordDispatcher = record
class procedure DoSomething<T: record>(const Value: T); static;
end;
class procedure TMyRecordDispatcher.DoSomething<T>(const Value: T);
begin
if TypeInfo(T) = TypeInfo(TPerson) then
DoSomethingWithThisPerson(PPerson(@Value)^)
else if TypeInfo(T) = TypeInfo(TSpider) then
DoSomethingWithThisSpider(PSpider(@Value)^);
end;
并像这样调用函数:
TMyRecordDispatcher.DoSomething(APerson);
TMyRecordDispatcher.DoSomething(ASpider);
这使用泛型类型推断,因此您无需显式声明类型。尽管作为泛型的一个例子,它让我感到畏缩。请不要这样做。
在我看来,所有这些都是混乱而脆弱的。上面的大部分重新实现 运行 时间方法分派,多态性。 类 更适合这个。我不认可上面的任何代码。
另一方面,也许这一切都是不必要的。有什么问题:
DoSomethingWithThisPerson(Person);
DoSomethingWithThisSpider(Spider);
既然你在编译时就知道类型,为什么要选择更复杂的东西?
您可以使用函数重载来省略函数名中的类型。
procedure DoSomething(const APerson: TPerson); overload;
begin
....
end;
procedure DoSomething(const ASpider: TSpider); overload;
begin
....
end;
....
DoSomething(Person);
DoSomething(Spider);