[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