![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
EExternalException.. [XP]
pathfinder © (2007-11-09 11:10:00)Добрый день.
Есть форма на которой edit и label. При изменении значения в edit-e оно должно меняться и label-е. Попытался сделать это с помощью шаблона Наблюдатель. Взял его реализацию из BDS2006. В методе NotifyObservers возникает EEXternalException при попытке вызвать метод Update элемента списка. Подскажите пожалуйста, в чем моя ошибка?
Код самой программы:
var
ProgParams: TProgParams;
ProgView: TProgView;
begin
ProgParams := TProgParams.Create;
ProgView := TProgView.Create(ProgParams);
ProgView.Show;
end.
Реализация классов:
type
TSubject = class;
IObserver = interface
procedure Update(ASubject :TSubject);
end;
TSubject = class
strict private var
FObservers:TList;
strict protected
procedure NotifyObservers;
public
constructor Create;
procedure Attach(AObserver :IObserver);
procedure Detach(AObserver :IObserver);
end;
TProgParams = class(TSubject)
strict private
FTest: string;
public
function GetParam(const Name: string): string;
procedure SetParam(const Name: string);
end;
TProgView = class(TInterfacedObject, IObserver)
strict private
FSubject: TProgParams;
FViewForm: TViewForm;
procedure Refresh;
procedure OnSetParam(Sender: TObject);
public
constructor Create(ASubject: TProgParams);
destructor Destroy;
procedure Show;
procedure Update(ASubject :TSubject);
end;
implementation
constructor TSubject.Create;
begin
inherited Create;
FObservers := TList.Create;
end;
procedure TSubject.Attach(AObserver :IObserver);
begin
FObservers.Add(@AObserver);
end;
procedure TSubject.Detach(AObserver :IObserver);
var
idx :Integer;
begin
idx := FObservers.IndexOf(@AObserver);
If idx <> -1 Then
begin
FObservers.Delete(idx);
end;
end;
procedure TSubject.NotifyObservers;
var
Current :^IObserver;
begin
for Current in FObservers do
Current.Update(self);
end;
constructor TProgView.Create(ASubject: TProgParams);
begin
FSubject := ASubject;
FSubject.Attach(self);
FViewForm := TViewForm.Create(nil);
FViewForm.edtTest.OnChange := OnSetParam;
end;
destructor TProgView.Destroy;
begin
FSubject.Detach(self);
FViewForm.Free;
end;
procedure TProgView.OnSetParam(Sender: TObject);
begin
FSubject.SetParam(FViewForm.edtTest.Text);
end;
procedure TProgView.Refresh;
var
s: string;
begin
s := FSubject.GetParam('');
FViewForm.edtTest.Text := s;
FViewForm.lblTest.Caption := s;
end;
procedure TProgView.Show;
begin
FViewForm.ShowModal;
end;
procedure TProgView.Update(ASubject :TSubject);
begin
Refresh;
end;
{ TProgParams }
function TProgParams.GetParam(const Name: string): string;
begin
Result := FTest;
end;
procedure TProgParams.SetParam(const Name: string);
begin
FTest := Name;
NotifyObservers;
end;
pathfinder (2007-11-09 13:46:00) [1]
> Сергей М. © (09.11.07 13:01) [16]
>
> Или приводи явно интерфейсный тип к указательному.
Воспользовался вашим советом и все заработало:)
Всем спасибо!
pathfinder (2007-11-09 13:37:00) [2]
> Так что вопрос к тебе в [12] вполне резонен.
Это готовая реализация этого шаблона из делфи. Получается они неправильно сделали?
Сергей М. (2007-11-09 13:31:00) [3]
> если FObservers.Add(@AObserver); то все ок
С т.з. компилятора - да.
А с т.з. происходящего при этом в ран-тайм - это полная фигня, о чем тебе и сообщает возникшее при этом исключение.
Так что вопрос к тебе в [12] вполне резонен.
pathfinder (2007-11-09 13:19:00) [4]
> Как же нормально, если при компиляции процитированных тобой
> в [15] строк компилятором обнаружена тобой же процитированная
> ошибка ?
>
Это если так FObservers.Add(AObserver);
А если FObservers.Add(@AObserver); то все ок.
Сергей М. (2007-11-09 13:14:00) [5]
> здесь то вроде все нормально
Как же нормально, если при компиляции процитированных тобой в [15] строк компилятором обнаружена тобой же процитированная ошибка ?
pathfinder (2007-11-09 13:07:00) [6]
> Сергей М. © (09.11.07 13:01) [16]
>
>
> > pathfinder © (09.11.07 12:57) [15]
>
>
> Ну так сделай FObservers типа TInterfaceList, бо на то этот
> тип и предназначен.
> Или приводи явно интерфейсный тип к указательному.
Так здесь то вроде все нормально..
Ошибка здесь:
TSubject.NotifyObservers;
Current.Update(self);
pathfinder (2007-11-09 13:05:00) [7]
> Конечно, надо делать более реальную задачу.
Не хотелось браться за сложное, если даже с простым не получается.
Anatoly Podgoretsky (2007-11-09 13:04:00) [8]> pathfinder (09.11.2007 12:57:14) [14]
Конечно, надо делать более реальную задачу.
Сергей М. (2007-11-09 13:01:00) [9]
> pathfinder © (09.11.07 12:57) [15]
Ну так сделай FObservers типа TInterfaceList, бо на то этот тип и предназначен.
Или приводи явноинтерфейсный тип к указательному.
pathfinder (2007-11-09 12:57:00) [10]
> icWasya © (09.11.07 12:51) [12]
>
> а почему так
> FObservers.Add(@AObserver);
>
> а не так
> FObservers.Add(AObserver);
> ???
[Pascal Error] Unit2.pas(60): E2010 Incompatible types: 'Pointer' and 'IObserver'
pathfinder (2007-11-09 12:57:00) [11]
> Anatoly Podgoretsky © (09.11.07 12:55) [13]
Большое спасибо! Это самый ценный совет.
Anatoly Podgoretsky (2007-11-09 12:55:00) [12]
> Я же говорю, что это не реальная задача, а просто для примера.
Тренируйся на кошках.
icWasya (2007-11-09 12:51:00) [13]а почему так
FObservers.Add(@AObserver);
а не так
FObservers.Add(AObserver);
???
pathfinder (2007-11-09 11:30:00) [14]И потом вопрос ведь не в том, как оптимальней решить ЭТУ задачу, а что не так в реализации?
pathfinder (2007-11-09 11:28:00) [15]
> Попробуй измерить время выполнения твоего алгоритма и предложенного
> товаришшем Ega23. Последний будет работать на порядок быстрее.
> Не для того этот шаблон создавался, чтоб на нём такое вытворяли.
>
Я же говорю, что это не реальная задача, а просто для примера.
Dib@zol (2007-11-09 11:27:00) [16]Попробуй измерить время выполнения твоего алгоритма и предложенного товаришшем Ega23. Последний будет работать на порядок быстрее. Не для того этот шаблон создавался, чтоб на нём такое вытворяли.
pathfinder (2007-11-09 11:25:00) [17]
> А нафика изобретать велосипед с треугольными колёсами? Поищи
> лучше в гугле задачи на применение этого шаблона, и не майся
> дурью. ЗЫ Мне аж плохо стало, когда я все эти навороты увидал.
> ..
Так какая разница какая задача? Вопрос-то в реализации..
Ega23 (2007-11-09 11:24:00) [18]
> Не стыдно, это же "батонокидательство"!
Это наиболее быстрый и дешёвый способ решения КОНКРЕТНОЙ проблемы.
Остальное - побоку.
Dib@zol (2007-11-09 11:24:00) [19]А нафика изобретать велосипед с треугольными колёсами? Поищи лучше в гугле задачи на применение этого шаблона, и не майся дурью. ЗЫ Мне аж плохо стало, когда я все эти навороты увидал...
ЮЮ (2007-11-09 11:22:00) [20]> [3] Ega23 © (09.11.07 11:19)
> Всё.
Не стыдно, это же "батонокидательство"!
А тут речь о Наблюдателе.
З.Ы. Не зря наблюдение за наблюдающим стоит дороже :)