[fpc-devel] Interface delegation fix: backport to FPC 2.4.2 ...?

Graeme Geldenhuys graemeg.lists at gmail.com
Thu May 20 00:41:01 CEST 2010


On 19/05/2010, Marco van de Voort wrote:
>
> First: I don't see an urgent need for such draconic measures.

So Michael having to wait 10 years to see it implemented is called
"urgent" in your eye?  :)


>  Second: I don't see a good solution, exactly because the whole framework was
>  not designed for this.

No need for a whole framework designed. Just adding some extra
functionality. Clearly you need a code example to understand it. See
the code example below.


>  E.g. an Observer pattern typically uses interfaces, and interfaces are not
>  designed into the framework.

Hell no! Observer has nothing to do with interfaces! The Observer is
implemented in tiOPF without interfaces. Using interfaces just makes
it easier to inject Observable behaviour - but injecting behaviour is
a feature of interfaces in general (not specific to Observer). The
other benefit of interfaces (now that we have interface delegation) is
that you only need to implement the Observer once and bolt that
implementation onto other classes. Saving you lots of duplicated code
and time.

Attached is a stripped down version of Observer implemented as a separate unit.

And here is how you can add Observer functionality to a class using
interfaces (purely to reduce code). This is what Michael and I are
proposing we do to base classes like TStrings or even TPersistent etc.

(note the final implementation my not look 100% like this - this is
just a quick example):


{$interfaces corba}

  TMyClass = class(TList, IFPObserved)
  private
    FObservedHook: TObservedHook;
    property  ObservedHook: TObservedHook read FObservedHook
implements IFPObserved; // are will always access it via a interface
so it can stay private
  public
     function Add(....): Integer; override;
  end;

function TMyClass.Add(....)
begin
  inherited Add(...)
  if Assigned(ObservedHook) then
    ObservedHook.NotifyObservers(self, ooChanged);
end;


That's it! Now TMyClass can be observed. No huge amounts of  code or
"draconic measures" as you phrased it.

You can now add observers of that class as follows in your program:

  TMakeMeObserveSomething = class(TObject, IFPObserver)
  private
     procedure ObservedChanged(ASender: TObject;
           Operation: TObservedOperation);
  public
     procedure DoItNow;
  end;

procedure TMakeMeObserveSomething.DoItNow;
var
  intf: IFPObserved;
begin
  if MyClass.GetInterface(IFPObserved, intf) then
    intf.AttachObserver(self);
end;


In tiOPF's implementation of Observer I optimized the code that extra
resources are only used when you actually use the observable
functionality by adding an observer the for the first time. I also
added extra optimization so that when you add many items for example
to a list that it works similar to BeginUpdate; .... EndUpdate; so
that observers are only notified once when a long running action is
completed or after multiple items was added to a list.  Similar
optimization could be added the what Michael is proposing (if he
hasn't implemented this yet).


-- 
Regards,
  - Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fpg_observer.pas
Type: text/x-pascal
Size: 4396 bytes
Desc: not available
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20100520/11815c06/attachment.pas>


More information about the fpc-devel mailing list