Originale-mail to me for new edition

 

Interface references

 

If you declare a variable of an interface type, the variable can reference instances of any class that implements the interface. Such variables allow you to call interface methods without knowing at compile time where the interface is implemented. But they are subject to the following limitations.

·    An interface-type expression gives you access only to methods and properties declared in the interface, not to other members of the implementing class.

·    An interface-type expression cannot reference an object whose class implements a descendant interface, unless the class (or one that it inherits from) explicitly implements the ancestor interface as well.

For example,

type

  IAncestor = interface

  end;

  IDescendant = interface(IAncestor)

    procedure P1;

  end;

  TSomething = class(TInterfacedObject, IDescendant)

    procedure P1;

    procedure P2;

  end;

  ...

var

  D: IDescendant;

  A: IAncestor;

begin

  D := TSomething.Create;  // works!

  A := TSomething.Create;  // error

  D.P1;  // works!

  D.P2;  // error

end;

In this example,

·    A is declared as a variable of type IAncestor. Because TSomething does not list IAncestor among the interfaces it implements, a TSomething instance cannot be assigned to A. But if we changed TSomething's declaration to

TSomething = class(TInterfacedObject, IAncestor, IDescendant)

 ...

the first error would become a valid assignment.

·    D is declared as a variable of type IDescendant. While D references an instance of TSomething, we cannot use it to access TSomething’s P2 method, since P2 is not a method of IDescendant. But if we changed D’s declaration to

D: TSomething;

the second error would become a valid method call.

Interface references are managed through reference-counting, which depends on the _AddRef and _Release methods inherited from IInterface. When an object is referenced only through interfaces, there is no need to destroy it manually; the object is automatically destroyed when the last reference to it goes out of scope.

Global interface-type variables can be initialized only to nil.

To determine whether an interface-type expression references an object, pass it to the standard function Assigned.

 

Interface assignment-compatibility

Interface typecasts

Interface querying

 

Topic groups

 

See also

Long strings

Object interfaces: Overview

 

 

译文

 

接口引用

 

如果声明了一个接口类型的变量,那么该变量可以引用任何实现了该接口的类的实例。这样的变量允许调用接口方法而不需要知道编译时哪一个接口被实现了。但它们受到下列约束:

·    接口类型的表达式仅给出了对接口中声明的方法的访问,而不是对实现接口的类中的其他成员。

·    接口类型的表达式不能引用实现后裔接口的类的对象,除非该类或其祖先类也实现了祖先接口。

例如,

type

  IAncestor = interface

  end;

  IDescendant = interface(IAncestor)

    procedure P1;

  end;

  TSomething = class(TInterfacedObject, IDescendant)

    procedure P1;

    procedure P2;

  end;

  ...

var

  D: IDescendant;

  A: IAncestor;

begin

  D := TSomething.Create;  // 正确运行

  A := TSomething.Create;  // 错误一

  D.P1;  // 正确运行

  D.P2;  // 错误二

end;

在上面的例子中,

·    A被声明为类型为IAncestor的变量。因为TSomething不能在其实现的接口中列出,所以TSomething实例不能被赋值给A。但如果将TSomething的声明改为

TSomething = class(TInterfacedObject, IAncestor, IDescendant)

 ...

那么错误一将成为有效的赋值语句。

·    D被声明为类型为IDescendant的变量。当D引用TSomething的实例时,不能用其访问TSomethingP2方法,因为P2不是IDescendant的方法。但如果将D的声明改为

D: TSomething;

那么错误二将成为有效的方法调用。

接口引用通过引用计数来管理,引用计数基于自IInterface继承的_AddRef_Release方法。当一个对象仅通过接口被引用时,不需要对其手工销毁;当最后的引用离开作用域时,该对象被自动销毁。

接口类型的全局变量只能被初始化为nil

要确定一个接口类型表达式是否是引用了一个对象,可以将其传递给标准函数Assigned

 

接口赋值兼容性

接口类型转换

接口查询

 

主题组

 

相关主题

长串

对象接口:概述