是否有一个技巧可以将不同类型的记录作为参数传递给过程?例如,看看这个伪代码:
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);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。