Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: Interface Delegation


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 3 - Last Post: Jan 12, 2017 10:21 AM Last Post By: Peter Below
Jan-Erich Schir...

Posts: 6
Registered: 3/1/02
Interface Delegation  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 11, 2017 1:17 AM
Hi,

Im trying to use delegated interfaces. Im using Model/View relationships with notification in the case of model changes.

The old and working way is to derive from a TModel, which has Methods like BeginChange, EndChange to encapsulate bulk-changes and notificates listeners on the last EndChange (Ref counter driven).

Often I need to equip existing classes with this model-capabilites. So the idea is to define a ISignal-interface with the methods mentioned. Then I want to implement these interface in a TSignal-class. Any other class shall now inherit from ISignal and delegate the functionality to a private object FSignal, wich is published as a property with the implements-keyword.

Like this
unit IModelFns;
 
interface
 
uses
  Classes;
 
type
  ISignal = interface;
 
  ISlot = interface
    procedure OnSignal(Sender :TObject);
  end;
 
  ISignal = interface
    procedure BeginChange;
    procedure EndChange;
    procedure Changed;
    procedure Register(Slot :ISlot);
  end;
 
  TSignal = class(TInterfacedObject, ISignal)
  private
    FSlot :ISlot;
    FHost :TObject;
    FChangeCount :integer;
    FChanged :boolean;
  protected
    procedure DoChanged; virtual;
  public
    constructor Create(Host :TObject);
    procedure BeginChange;
    procedure EndChange;
    procedure Changed;
    procedure Register(Slot :ISlot);
  end;
 
implementation
...


Now I create a Form1, which inherits from TForm and ISignal

  TForm1 = class(TForm, ISignal)
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
  private
    FSignal :ISignal;
  public
    property Signal :ISignal read FSignal implements ISignal;
  end;


Now I create a Form2 which links to Form1 and reflects the changing contents of Form1.Edit1 in Form2.Label2

  TForm2 = class(TForm, ISlot)
    Label1: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure OnSignal(Sender :TObject);
  public
    { Public-Deklarationen }
  end;
 
var
  Form2: TForm2;
 
implementation
 
{$R *.dfm}
 
procedure TForm2.Button1Click(Sender: TObject);
begin
  Form1.Signal.Register(self);
end;
 
procedure TForm2.OnSignal(Sender: TObject);
begin
  Label1.Caption := (Sender as TForm1).Edit1.Text;
end;
 


So far it works fine. BUT:

To link Form2 to Form2 I click in Button1 and
Form1.Signal.Register(self);

Now the great Question: Why cant I call it this way

Form1.Register(self);

Form1 has ISignal in its anchestor list. But the compiler doesnt allow the direct call. Instead I have to call the
Register-method of the delegate. This would work even without all that interface stuff. Whats wrong with my idea?
Peter Below

Posts: 1,227
Registered: 12/16/99
Re: Interface Delegation  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 11, 2017 10:58 PM   in response to: Jan-Erich Schir... in response to: Jan-Erich Schir...
Jan-Erich Schirrmacher wrote:

Hi,

Im trying to use delegated interfaces. Im using Model/View
relationships with notification in the case of model changes.

The old and working way is to derive from a TModel, which has Methods
like BeginChange, EndChange to encapsulate bulk-changes and
notificates listeners on the last EndChange (Ref counter driven).

Often I need to equip existing classes with this model-capabilites.
So the idea is to define a ISignal-interface with the methods
mentioned. Then I want to implement these interface in a
TSignal-class. Any other class shall now inherit from ISignal and
delegate the functionality to a private object FSignal, wich is
published as a property with the implements-keyword.

Like this
unit IModelFns;
 
interface
 
uses
  Classes;
 
type
  ISignal = interface;
 
  ISlot = interface
    procedure OnSignal(Sender :TObject);
  end;
 
  ISignal = interface
    procedure BeginChange;
    procedure EndChange;
    procedure Changed;
    procedure Register(Slot :ISlot);
  end;
 
  TSignal = class(TInterfacedObject, ISignal)
  private
    FSlot :ISlot;
    FHost :TObject;
    FChangeCount :integer;
    FChanged :boolean;
  protected
    procedure DoChanged; virtual;
  public
    constructor Create(Host :TObject);
    procedure BeginChange;
    procedure EndChange;
    procedure Changed;
    procedure Register(Slot :ISlot);
  end;
 
implementation
...


Now I create a Form1, which inherits from TForm and ISignal

  TForm1 = class(TForm, ISignal)
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Edit1Change(Sender: TObject);
  private
    FSignal :ISignal;
  public
    property Signal :ISignal read FSignal implements ISignal;
  end;


Now I create a Form2 which links to Form1 and reflects the changing
contents of Form1.Edit1 in Form2.Label2

  TForm2 = class(TForm, ISlot)
    Label1: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    procedure OnSignal(Sender :TObject);
  public
    { Public-Deklarationen }
  end;
 
var
  Form2: TForm2;
 
implementation
 
{$R *.dfm}
 
procedure TForm2.Button1Click(Sender: TObject);
begin
  Form1.Signal.Register(self);
end;
 
procedure TForm2.OnSignal(Sender: TObject);
begin
  Label1.Caption := (Sender as TForm1).Edit1.Text;
end;
 


So far it works fine. BUT:

To link Form2 to Form2 I click in Button1 and
Form1.Signal.Register(self);

Now the great Question: Why cant I call it this way

Form1.Register(self);

You would have to call it as

(form1 as ISgnal).Register(self);

The form class itself does not have a public Register method, so the
compiler does not allow your first construct.

Interfaces in Delphi do not work like in C++ (if I understand the
latter correctly). A class does not inherit methods from an interface,
it implements the methods of the interface. They are only callable
directly on a class reference if they have sufficient visibility scope
(public usually). In that case they behave like normal methods, the
interface does not come into play at all. You need to call the methods
using an interface reference to access them in cases like yours, where
the implementation is delegated to another class.

--
Peter Below
TeamB

Jan-Erich Schir...

Posts: 6
Registered: 3/1/02
Re: Interface Delegation  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 12, 2017 7:43 AM   in response to: Jan-Erich Schir... in response to: Jan-Erich Schir...
Thanks Peter. I worked with Java and found Interfaces a useful technique for a lot of problems. But in Delphi I never found a way to
use them, which saves work for me. The only good example I found in a library for GDIPlus. But there the feature of lifetime control from COM-objects was important, not the idea of interfaces itself.
Peter Below

Posts: 1,227
Registered: 12/16/99
Re: Interface Delegation  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 12, 2017 10:21 AM   in response to: Jan-Erich Schir... in response to: Jan-Erich Schir...
Jan-Erich Schirrmacher wrote:

Thanks Peter. I worked with Java and found Interfaces a useful
technique for a lot of problems. But in Delphi I never found a way to
use them, which saves work for me. The only good example I found in a
library for GDIPlus. But there the feature of lifetime control from
COM-objects was important, not the idea of interfaces itself.

I find them very useful, both for lifetime control and for abstracting
a set of functionality that may be implemented by classes that do not
share an ancestor beyond TInterfacedObject.

If you build applications the standard RAD way (which I do not beyond
designing forms for the UI) interfaces do not have that much use, since
the standard components are all designed to work with object
references. But if you design with a clear object model for your data
and a good separation of functionality into layers interfaces are very
useful, IMO.

--
Peter Below
TeamB
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02