I'd like to create a generic Subject Interface and so reuse it with "specifics" Observer classes. So I tried this code for the Subject:
unit uISubject;
interface
type
ISubject = interface(IInterface)
procedure RegisterObserver(Observer: IInterface);
procedure RemoveObserver(Observer: IInterface);
procedure NotifyObservers;
end;
implementation
end.
And I have the following classes for Observers:
An Observer for serial communication
unit uISerialObserver;
interface
type
ISerialObserver = interface(IInterface)
['{EF833BD7-31C1-49B3-8041-F1574AC043F0}']
procedure DataAvailable(ReceivedData: AnsiString);
end;
implementation
end.
An Observer that update Progress bar
unit uIProgressObserver;
interface
type
IProgressObserver = interface(IInterface)
['{05AC7C76-CD41-42AB-B793-1512E68D91D5}']
procedure UpdateProgressParameters(Min, Max: Cardinal);
procedure IncrementParameter;
end;
implementation
end.
And I've implemented the Notify method like this:
procedure TSerialPortCommunicator.NotifyObservers;
var
Obs: IInterface;
begin
for Obs in FObservers do
begin
ISerialObserver(Obs).UpdateObserver(FReceivedData);
end;
end;
where
FObservers: TList<IInterface>;
When NotifyObservers
runs, Delphi returns an Access Violation Error.
I'd like to know what I'm doing wrong?
You need to cast the interface with a dynamic cast using the as
operator.
Your code, ISerialObserver(IInterface(Obs))
, is a certain point of failure. You should instead write Obs as ISerialObserver
. But why not make your list TList<ISerialObserver>
and thus avoid the cast?
That said, are you sure everything in your list implements ISerialObserver
? It's not obvious from these excerpts. You can check for interface support with the is
operator, or the rather more functional Supports()
function.
Also, you don't need to inherit from IInterface, that is implicit. So you can replace ISubject = interface(IInterface)
with ISubject = interface
and so on.