🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.delphi.language.objectpascal
Article #40

Re: typecasting interfaces

#40
From: Skybuck Flying
Date: Thu, 08 Sep 2005 14:41
211 lines
5833 bytes
Hi,

Interesting problem.

The solution is simple.. at least for me since I have been coding in delphi
for many years... but I never use interfaces though I am still able to solve
your problem =D

The problem is with these two lines:

>     if Components[i] is tFrame then begin

Tframe does not contain any interfaces.

>       F := Components[i] as ImyInterf;   // ---- Error

Tcomponent does not implement any interfaces therefore it's not allowed to
use the "as" operator in combination with an interface type as above. This
is only allowed if the class implements an interface as described in the
delphi help:

"
Using the as operator with interfaces

Classes that implement interfaces can use the as operator for dynamic
binding on the interface. In the following example,

procedure PaintObjects(P: TInterfacedObject)
var
  X: IPaint;
begin
  X := P as IPaint;
{ statements }
end;

the variable P of type TInterfacedObject, can be assigned to the variable X,
which is an IPaint interface reference. Dynamic binding makes this
assignment possible. For this assignment, the compiler generates code to
call the QueryInterface method of P's IInterface interface. This is because
the compiler cannot tell from P's declared type whether P's instance
actually supports IPaint. At runtime, P either resolves to an IPaint
reference or an exception is raised. In either case, assigning P to X will
not generate a compile-time error as it would if P was of a class type that
did not implement IInterface.

When you use the as operator for dynamic binding on an interface, you should
be aware of the following requirements:

Explicitly declaring IInterface: Although all interfaces derive from
IInterface, it is not sufficient, if you want to use the as operator, for a
class to simply implement the methods of IInterface. This is true even if it
also implements the interfaces it explicitly declares. The class must
explicitly declare IInterface in its interface list.
 Using an IID: Interfaces can use an identifier that is based on a GUID
(globally unique identifier). GUIDs that are used to identify interfaces are
referred to as interface identifiers (IIDs). If you are using the as
operator with an interface, it must have an associated IID. To create a new
GUID in your source code you can use the Ctrl+Shift+G editor shortcut key.
"

The solution is to create a special version of Tframe which does contain an
interface like so:

TmyInterfacedFrame = class(Tframe, ImyInterface)
etc

This will be an abstract class where all other frames are to be derived
from.

Here is a complete example:

// unit1:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Unit3, Unit2;

type
  TForm1 = class(TForm)
    Frame21: TFrame2;
    Frame31: TFrame3;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
 unit4;

procedure TForm1.Button1Click(Sender: TObject);
var   I : integer;
   F : ImyInterface;
begin
  for I := 0 to ComponentCount -1 do
  begin
 if Components[i] is TmyInterfacedFrame then
 begin
   F := Components[i] as TmyInterfacedFrame;
   F.doit;
 end;
  end;
end;

end.

// unit2:

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Unit4;

type
  TFrame2 = class(TmyInterfacedFrame)
    Memo1: TMemo;
  private
    { Private declarations }
  public
 { Public declarations }
 procedure DoIt; override;
  end;

implementation

{$R *.dfm}

procedure TFrame2.DoIt;
begin
 ShowMessage('do it 2');
end;

end.

// unit3

unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Unit4;

type
  TFrame3 = class(TmyInterfacedFrame)
    Button1: TButton;
  private
    { Private declarations }
  public
 { Public declarations }
 procedure DoIt; override;
  end;

implementation

{$R *.dfm}

procedure TFrame3.DoIt;
begin
 ShowMessage('do it 3');
end;

end.

unit Unit4;

interface

uses
 Forms;

type
 ImyInterface = interface
  procedure DoIt;
 end;

 TmyInterfacedFrame = class(Tframe, ImyInterface)
  procedure DoIt; virtual; abstract;
 end;

implementation

end.

Note:

DoIt is now a virtual method.

All frames which are derived from TmyInterfaceFrame need to override the
"DoIt" method otherwise the virtual abstract method will be called which has
no implementation so then an EAbstractError exception is raised.

Bye,
  Skybuck.
Technical Details
Message-ID: <dfpiac$qc7$1@news6.zwoll1.ov.home.nl>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!news.glorb.com!feeder.enertel.nl!nntpfeed-01.ops.asmr-01.energis-idc.net!newshub3.home.nl!newshub1.home.nl!home.nl!not-for-mail
References: <1ob7c15f14llkd5g8iup0d5fqpe9igt23d@4ax.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: 109d30,8f058075853262b4
X-Google-Attributes: gid109d30,public
X-Google-Language: ENGLISH,ASCII-7-bit
Path: arc1-ca.pugleaf.net!g2news1.google.com!news4.google.com!news.glorb.com!feeder.enertel.nl!nntpfeed-01.ops.asmr-01.energis-idc.net!newshub3.home.nl!newshub1.home.nl!home.nl!not-for-mail
From: "Skybuck Flying" <nospam@hotmail.com>
Newsgroups: borland.public.delphi.language.objectpascal
Subject: Re: typecasting interfaces
Date: Thu, 8 Sep 2005 16:41:00 +0200
Organization: @Home Benelux
Lines: 213
Message-ID: <dfpiac$qc7$1@news6.zwoll1.ov.home.nl>
References: <1ob7c15f14llkd5g8iup0d5fqpe9igt23d@4ax.com>
NNTP-Posting-Host: cp250405-a.landg1.lb.home.nl
X-Trace: news6.zwoll1.ov.home.nl 1126190220 27015 84.25.126.9 (8 Sep 2005 14:37:00 GMT)
X-Complaints-To: usenet@corp.home.nl
NNTP-Posting-Date: Thu, 8 Sep 2005 14:37:00 +0000 (UTC)
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1506
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1506