12.8.8 Class operators

Class operators are slightly different from the operators above in the sense that they can only be used in class expressions which return a class. There are only two class operators, as can be seen in table (12.8).


Table 12.8: Class operators

OperatorAction


is Checks class type
as Conditional typecast

An expression containing the is operator results in a boolean type. The is operator can only be used with a class reference or a class instance. The usage of this operator is as follows:

 Object is Class

This expression is completely equivalent to

 Object.InheritsFrom(Class)

If Object is Nil, False will be returned.

The following are examples:

Var  
  A : TObject;  
  B : TClass;  
 
begin  
  if A is TComponent then ;  
  If A is B then;  
end;

The as operator performs a conditional typecast. It results in an expression that has the type of the class:

  Object as Class

This is equivalent to the following statements:

  If Object=Nil then  
    Result:=Nil  
  else if Object is Class then  
    Result:=Class(Object)  
  else  
    Raise Exception.Create(SErrInvalidTypeCast);

Note that if the object is nil, the as operator does not generate an exception.

The following are some examples of the use of the as operator:

Var  
  C : TComponent;  
  O : TObject;  
 
begin  
  (C as TEdit).Text:='Some text';  
  C:=O as TComponent;  
end;

The as and is operators also work on interfaces (both COM and CORBA). They can be used to check whether an interface also implements another interface as in the following example:

{$mode objfpc}  
 
uses  
  SysUtils;  
 
type  
  IMyInterface1 = interface  
    ['{DD70E7BB-51E8-45C3-8CE8-5F5188E19255}']  
    procedure Bar;  
  end;  
 
  IMyInterface2 = interface  
    ['{7E5B86C4-4BC5-40E6-A0DF-D27DBF77BCA0}']  
    procedure Foo;  
  end;  
 
  TMyObject = class(TInterfacedObject, IMyInterface1, IMyInterface2)  
    procedure Bar;  
    procedure Foo;  
  end;  
 
procedure TMyObject.Bar;  
begin  
 
end;  
 
procedure TMyObject.Foo;  
begin  
 
end;  
 
var  
  i: IMyInterface1;  
begin  
  i := TMyObject.Create;  
  i.Bar;  
  Writeln(BoolToStr(i is IMyInterface2, True)); // prints true  
  Writeln(BoolToStr(i is IDispatch, True)); // prints false  
  (i as IMyInterface2).Foo;  
end.

Additionally, the is operator can be used to check if a class implements an interface, and the as operator can be used to typecast an interface back to the class:

{$mode objfpc}  
var  
  i: IMyInterface;  
begin  
  i := TMyObject.Create;  
  Writeln(BoolToStr(i is TMyObject,True)); // prints true  
  Writeln(BoolToStr(i is TObject,True)); // prints true  
  Writeln(BoolToStr(i is TAggregatedObject,True)); // prints false  
  (i as TMyObject).Foo;  
end.

Although the interfaces must be COM interfaces, the typecast back to a class will only work if the interface comes from an Object Pascal class. It will not work on interfaces obtained from the system by COM.