【问题标题】:many Interfaces heritage in delphidelphi中的许多接口遗产
【发布时间】:2017-10-22 17:44:38
【问题描述】:

我希望继承一些 D 类的遗产,并实现接口 A、B 和 C 的所有属性和方法。请帮我提供 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;

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

【问题讨论】:

  • 只需删除“覆盖”指令。 “覆盖”用于覆盖在祖先类中声明为“虚拟”的方法。祖先类“TInterfacedObject”中不存在您的 8 个方法。
  • 哦,谢谢,但现在我很困惑。如果我删除覆盖,如何保证我不会收到抽象错误?你有什么想法吗?
  • 你的类实现了所有的接口方法。只是在实现接口方法时不需要指定override,只需virtual类方法即可。这段代码没有抽象错误。

标签: oop delphi interface


【解决方案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;

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

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

【讨论】:

  • 您链接的SO问题与接口问题背后的虚拟方法无关。
  • 是的,我认为你是对的 Stefan。我抓住了错误的答案。我会看看我以后能不能找到正确的。谢谢。
  • Stefan,我虽然有一个问题的链接来解释这一点,但碰巧我找不到它。无论如何,答案已更新为 Andreas Hausladen 博客文章的链接,该文章解释了性能差异背后的原因。再次感谢!
【解决方案2】:

从您的代码中删除 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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-17
    • 2020-12-27
    • 2015-11-06
    • 2011-10-01
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多