我希望制作一些D类传统并实现接口A,B和C的所有属性和方法。请帮我解决Delphi中的一个例子。
我使用的是Delphi 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;
它不起作用,因为有许多错误,例如“在基类中找不到刷新”,
答案 0 :(得分:1)
从代码中删除override
字,因为interface
方法实现没有明确的method binding directive。您在代码中使用的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;
答案 1 :(得分:1)
您至少有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;
最后一点:Case(3)表现最佳。在接口上调用虚方法会导致性能损失,这可能与您的特定应用程序相关,也可能不相关。
PS:正如Stefan所指出的,我与另一个SO问题的联系是错误的。但是,您可以阅读Andreas Hausladen博客通过界面调用的虚拟方法的性能:http://andy.jgknet.de/blog/2016/05/whats-wrong-with-virtual-methods-called-through-an-interface/