这两组代码有什么区别

时间:2020-03-06 15:01:47  来源:igfitidea点击:

这两段代码有什么区别

type
  IInterface1 = interface
    procedure Proc1;
  end;

  IInterface2 = interface
    procedure Proc2;
  end;

  TMyClass = class(TInterfacedObject, IInterface1, IInterface2)
  protected
    procedure Proc1;
    procedure Proc2;
  end;

以及以下内容:

type
  IInterface1 = interface
    procedure Proc1;
  end;

  IInterface2 = interface(Interface1)
    procedure Proc2;
  end;

  TMyClass = class(TInterfacedObject,  IInterface2)
  protected
    procedure Proc1;
    procedure Proc2;
  end;

如果它们是相同的,那么两者之间是否存在任何优势或者可读性问题。

我想第二种方法意味着我们必须编写一个实现IInterface2的类而不实现IInterface1,而第一种方法则可以。

解决方案

假设你的意思

...
IInterface2 = interface(Interface1)
...

我和我们解释的一样,第二种形式也需要一个实现Interface2的类来实现Interface1,而第一种形式则不需要。

I guess the second means you cannot write a class that implements IInterface2 without implementing IInterface1, whilst with the first you can.

那将是技术上的差异。

哪一个更好取决于很大程度上取决于接口。如果IInterface2既不是IInterface1,也存在吗?

如果IInterface1是"可显示的"而IInterface2是"可存储的",则第一个选项可能更有意义。如果IInterface1是"车辆",而IInterface2是"卡车",则第二个选项可能更有意义。

首先,我假设IInterface2的第二个示例的声明是一个错字,应为

IInterface2 = interface(Interface1)

因为从自身继承是毫无意义的(即使编译器接受了)。

"继承"是在那里回答问题的关键词。在示例1中,两个接口是完全独立的,我们可以实现一个,另一个或者两个都没有问题。在示例2中,我们正确地知道,如果不同时实现interface1也不能实现interface2,但是之所以如此,是因为它使interface1成为interface2的一部分。

因此,区别主要是结构和组织上的差异,而不仅仅是可读性。

如果我们谈论的是用于Win32的Delphi(Delphi for .NET具有不同的规则),则这两个代码段的效果非常不同,并且几乎没有等效。

  • 实现其接口的类必须实现该接口的祖先的所有成员,但不会隐式实现祖先。因此,在第二种情况下,尝试将类型为TMyClass的实例分配给类型为IInterface1的位置将失败。
  • 与上一点有关,如果IInterface1和IInterface2都具有GUID,则在第二种情况下,目标类型为IInterface1的接口引用的动态转换(使用" Supports"或者" as")将失败。
  • 接口IInterface2在第二种情况下有一个额外的方法,而在第一种情况下则没有。
  • 在第二种情况下,类型IInterface2的值可分配给类型IInterface1的位置。对于第一种情况,情况并非如此。

在此示例中自己看看:

type
      A_I1 = interface
      end;

      A_I2 = interface(A_I1)
      end;

      A_Class = class(TInterfacedObject, A_I2)
      end;

    procedure TestA;
    var
      a: A_Class;
      x: A_I1;
    begin
      a := A_Class.Create;
      x := a; // fails!
    end;

    type
      B_I1 = interface
      end;

      B_I2 = interface
      end;

      B_Class = class(TInterfacedObject, B_I1, B_I2)
      end;

    procedure TestB;
    var
      a: B_Class;
      x: B_I1;
    begin
      a := B_Class.Create;
      x := a; // succeeds!
    end;

    begin
      TestA;
      TestB;
    end.