德尔福的许多界面遗产



我希望做一些D类遗产,并实现接口A,B和C的所有属性和方法。请帮助我用德尔福的例子。

我使用德尔福Xe7一个类如何实现多个接口?我正在尝试类似的东西:

Unit1
Type
IRefresher = Interface
['{B289720C-FFA4-4652-9F16-0826550DFCF9}']
procedure Refresh;
function getRefreshed: boolean;
property Refreshed:Boolean read getRefreshed;
End;

Unit2
Type
IRecorder = Interface
['{AB447097-C654-471A-A06A-C65CE5606721}']
procedure Reader;
procedure Writer;
end;

Unit3
ICustomer=Interface ['{F49C0018-37DA-463D-B5B4-4ED76416C7D4}']
procedure SetName(Value:String);
procedure SetDocument(Value:String);
function getName:String;
function getDocument:String;
End;

Unit4
Uses Unit1,Unit2,Unit3;
TGovernmentCustomer = class(TInterfacedObject, ICustomer, IRecorder,
IRefresher)
a: String;
public
{$REGION 'Customer'}
procedure SetName(Value: String); override;
procedure SetDocument(Value: String);
function getName: String; override;
function getDocument: String; override;
{$ENDREGION}
{$REGION 'Recorder'}
procedure Reader; override;
procedure Writer; override;
{$ENDREGION}
{$REGION 'Refresher'}
procedure Refresh; override; 
function getRefreshed: boolean; override;
{$ENDREGION}
End;

它不起作用,因为许多错误,例如"在基类中找不到刷新",

您至少有 3 个实现选项:

1)虚拟和抽象方法。在这种情况下,不能实例化此类,并且必须重写后代类中的抽象方法。这样的方法如下所示:

type
TGovernmentCustomer = class(TInterfacedObject, ICustomer, IRecorder, IRefresher)
a: String;
public
procedure SetName(Value: String); virtual; abstract;
end;

一旦方法抽象,就没有实现。

2)虚拟方法。在这种情况下,您可以实例化此类,并且可以重写后代类中的某些虚拟方法。这样的方法如下所示:

type
TGovernmentCustomer = class(TInterfacedObject, ICustomer, IRecorder, IRefresher)
a: String;
public
procedure SetName(Value: String); virtual;
end;
implementation
procedure TGovernmentCustomer.SetName(Value: String);
begin
// do something here. You can also leave it empty
end;

3)静态方法。在这种情况下,您可以实例化此类,并且不能重写后代类中的静态方法。这样的方法如下所示:

type
TGovernmentCustomer = class(TInterfacedObject, ICustomer, IRecorder, IRefresher)
a: String;
public
procedure SetName(Value: String);
end;
implementation
procedure TGovernmentCustomer.SetName(Value: String);
begin
// do something here. This will be the behavior of all instances of this class and descendant classes if they exist
end;

最后一点:案例(3)具有最佳性能。在接口上调用虚拟方法会降低性能,这可能与您的特定应用程序相关,也可能不相关。

PS:正如Stefan所指出的,我链接到另一个SO问题是错误的。但是,您可以从Andreas Hausladen博客中阅读有关通过接口调用的虚拟方法的性能:http://andy.jgknet.de/blog/2016/05/whats-wrong-with-virtual-methods-called-through-an-interface/

从代码中删除override字,因为interface方法实现没有显式的方法绑定指令。您在代码中使用的override指令仅适用于即将由当前类实现的祖先类的virtual(abstract)或dynamic类方法。

下面是一个示例,该示例演示了使用接口的伪抽象类的override指令的含义(代码中的示例):

type
ICustomer = interface
['{F49C0018-37DA-463D-B5B4-4ED76416C7D4}']
procedure SetName(Value: string);
end;
IRefresher = interface
['{B289720C-FFA4-4652-9F16-0826550DFCF9}']
procedure Refresh;
end;
// sort of "abstract" class (not precisely) that does not yet "implement"
// the methods of the interfaces, only "includes" the interfaces
TAnyCustomer = class(TInterfacedObject, ICustomer, IRefresher)
private
FSomething: string;
public
// though the interfaces are "included" as a part of this class, their
// method implementation is not yet specific (missing implementantion
// exception is raised only, which is self-explaining, I'd say); that
// "virtual" directive of the following class methods lets this class'
// descendants "override" them to write the specific implementation
procedure SetName(Value: string); virtual;
procedure Refresh; virtual;
end;
// specific implementation of the class defined above; here you "override"
// the virtual methods of the "abstract" class defined above and implement
// the specific behavior of the class
TGovernmentCustomer = class(TAnyCustomer)
public
// "override" the ancestor's class method behavior and write a specific
// implementation (which finally implements some specific functionality
// here)
procedure SetName(Value: string); override;
procedure Refresh; override;
end;
implementation
procedure TAnyCustomer.SetName(Value: string);
begin
raise ENotImplemented.Create('Ouch! You missed to implement me!');
end;
procedure TAnyCustomer.Refresh;
begin
raise ENotImplemented.Create('Ouch! You missed to implement me!');
end;
procedure TGovernmentCustomer.SetName(Value: string);
begin
ShowMessage('I''m a government customer. How can I increase your budget?');
end;
procedure TGovernmentCustomer.Refresh;
begin
ShowMessage('Tell someone I''m fresh!');
end;

最新更新