comm1x писал(а):
Не, не забили. Я совершенно не понимаю о чем вы ведете диалог.
Есть разные варианты, в зависимости от задач. Тот что я показал - из разряда "наскоряк пойдёт для одного раза".
Если каждая отрисовка имеет свои параметры (различные для разных объектов), то делать можно так:
Основной модуль:
Код:
MODULE PrivViews;
IMPORT
Views;
TYPE
Drawer* = POINTER TO ABSTRACT RECORD
v- : View; (* при отрисовке мы должны использовать данные объекта *)
END;
View* = POINTER TO RECORD(Views.View)
d : Drawer (*у каждого объекта в каждый момент времени - один рисователь*)
END;
DefDrawer = POINTER TO RECORD (Drawer) (* изначально объект рисоваться не умеет - это заглушка *)
END;
PROCEDURE (d : Drawer) Draw- (f : Views.Frame; l, t, r, b : INTEGER), NEW, ABSTRACT;
PROCEDURE (d : DefDrawer) Draw- (f : Views.Frame; l, t, r, b : INTEGER);
BEGIN
END Draw;
PROCEDURE (v : View) Restore* (f : Views.Frame; l, t, r, b : INTEGER);
BEGIN
(* если бы не ввели DefDrawer, то здесь пришлось бы проверять на v.d # NIL *)
v.d.Draw(f, l, t, r, b)
END Restore;
(* меняем рисователь для объекта *)
PROCEDURE SetDrawer* (v : View; d : Drawer);
BEGIN
ASSERT (v # NIL, 20);
ASSERT (d # NIL, 21);
v.d := d; d.v := v
END SetDrawer;
(* создаём объект с пустым рисователем. Никто не мешает нам создать его и простым NEW, но тогда он не будет правильно инициализирован. Можно и это предусмотреть, но для примера - сойдёт *)
PROCEDURE New* () : View;
VAR res : View; d : DefDrawer;
BEGIN
NEW(res); NEW(d); SetDrawer(res, d); RETURN res
END New;
PROCEDURE Deposit*;
BEGIN
Views.Deposit(New())
END Deposit;
END PrivViews.
Модуль реализации рисователей:
Код:
MODULE PrivViewDrawers;
IMPORT
PrivViews, Views;
TYPE
SinDrawer = POINTER TO RECORD (PrivViews.Drawer)
END;
CosDrawer = POINTER TO RECORD (PrivViews.Drawer)
END;
TanDrawer = POINTER TO RECORD (PrivViews.Drawer)
END;
PROCEDURE (d : SinDrawer) Draw- (f : Views.Frame; l, t, r, b : INTEGER);
BEGIN
тут рисуем синус
END Draw;
PROCEDURE (d : CosDrawer) Draw- (f : Views.Frame; l, t, r, b : INTEGER);
BEGIN
тут рисуем косинус
END Draw;
PROCEDURE (d : TanDrawer) Draw- (f : Views.Frame; l, t, r, b : INTEGER);
BEGIN
тут рисуем тангенс
END Draw;
PROCEDURE SetSinDrawer* (v : Views.View);
VAR s : SinDrawer;
BEGIN
WITH v : PrivViews.View DO
NEW(s); PrivViews.SetDrawer(v, s)
ELSE
END
END SetSinDrawer;
PROCEDURE SetCosDrawer* (v : Views.View);
VAR c : CosDrawer;
BEGIN
WITH v : PrivViews.View DO
NEW(c); PrivViews.SetDrawer(v, c)
ELSE
END
END SetCosDrawer;
PROCEDURE SetTanDrawer* (v : Views.View);
VAR t : TanDrawer;
BEGIN
WITH v : PrivViews.View DO
NEW(t); PrivViews.SetDrawer(v, t)
ELSE
END
END SetTanDrawer;
END PrivViewDrawers.
Пользуемся например так:
Код:
PROCEDURE DepositTan;
VAR v : Views.View;
BEGIN
v := PrivViews.New(); PrivViewDrawers.SetTanDrawer(v); Views.Deposit(v)
END DepositTan;