История изменений
Исправление LongLiveUbuntu, (текущая версия) :
Ты очень легко изобретешь Си с классами и сам. Просто попробуй. А для затравочки вот тебе пример кода на Обероне, который построен примерно в той же парадигме:
Вот тут просто дергаем процедуры в стиле C++
MODULE Figures; (* Abstract module *)
TYPE
Figure* = POINTER TO FigureDesc;
Interface* = POINTER TO InterfaceDesc;
InterfaceDesc* = RECORD
draw* : PROCEDURE (f : Figure);
clear* : PROCEDURE (f : Figure);
mark* : PROCEDURE (f : Figure);
move* : PROCEDURE (f : Figure; dx, dy : INTEGER);
END;
FigureDesc* = RECORD
if : Interface;
END;
PROCEDURE Init* (f : Figure; if : Interface);
BEGIN
f.if := if;
END Init;
PROCEDURE Draw* (f : Figure);
BEGIN
f.if.draw(f);
END Draw;
(* Other procedures here *)
END Figures.
MODULE Rectangles;
IMPORT Figures;
TYPE
Rectangle* = POINTER TO RectangleDesc;
RectangleDesc* = RECORD
(Figures.FigureDesc)
x, y, w, h : INTEGER;
END;
VAR
if : Figures.Interface;
PROCEDURE New* (VAR r : Rectangle);
BEGIN
NEW(r);
Figures.Init(r, if);
END New;
PROCEDURE Draw* (f : Figure);
VAR
r : Rectangle;
BEGIN
r := f(Rectangle); (* f AS Rectangle *)
(* ... *)
END Draw;
(* Other procedures here *)
BEGIN (* Module initialisation *)
NEW(if);
if.draw := Draw;
if.clear := Clear;
if.mark := Mark;
if.move := Move;
END Rectangles.
А тут отправляем сообщения в стиле Smalltalk или Objective-C.
MODULE Figures; (* Abstract module *)
TYPE
Figure* = POINTER TO FigureDesc;
Message* = RECORD END;
DrawMsg* = RECORD (Message) END;
ClearMsg* = RECORD (Message) END;
MarkMsg* = RECORD (Message) END;
MoveMsg* = RECORD (Message) dx*, dy* : INTEGER END;
Handler* = PROCEDURE (f : Figure; VAR msg : Message);
FigureDesc* = RECORD
(* Abstract *)
handle : Handler;
END;
PROCEDURE Handle* (f : Figure; VAR msg : Message);
BEGIN
f.handle(f, msg);
END Handle;
PROCEDURE Init* (f : Figure; handle : Handler);
BEGIN
f.handle := handle;
END Init;
END Figures.
MODULE Rectangles;
IMPORT Figures;
TYPE
Rectangle* = POINTER TO RectangleDesc;
RectangleDesc* = RECORD
(Figures.FigureDesc)
x, y, w, h : INTEGER;
END;
PROCEDURE Draw* (r : Rectangle);
BEGIN
(* ... *)
END Draw;
(* Other procedures here *)
PROCEDURE Handle* (f: Figure; VAR msg: Figures.Message);
VAR
r : Rectangle;
BEGIN
r := f(Rectangle);
IF msg IS Figures.DrawMsg THEN Draw(r)
ELSIF msg IS Figures.MarkMsg THEN Mark(r)
ELSIF msg IS Figures.MoveMsg THEN Move(r, msg(Figures.MoveMsg).dx, msg(Figures.MoveMsg).dy)
ELSE (* ignore *)
END
END Handle;
PROCEDURE New* (VAR r : Rectangle);
BEGIN
NEW(r);
Figures.Init(r, Handle);
END New;
END Rectangles.
Исходная версия LongLiveUbuntu, :
Ты очень легко изобретешь Си с классами и сам. Просто попробуй. А для затравочки вот тебе пример кода на Обероне, который построен примерно в той же парадигме:
MODULE Figures; (* Abstract module *)
TYPE
Figure* = POINTER TO FigureDesc;
Interface* = POINTER TO InterfaceDesc;
InterfaceDesc* = RECORD
draw* : PROCEDURE (f : Figure);
clear* : PROCEDURE (f : Figure);
mark* : PROCEDURE (f : Figure);
move* : PROCEDURE (f : Figure; dx, dy : INTEGER);
END;
FigureDesc* = RECORD
if : Interface;
END;
PROCEDURE Init* (f : Figure; if : Interface);
BEGIN
f.if := if;
END Init;
PROCEDURE Draw* (f : Figure);
BEGIN
f.if.draw(f);
END Draw;
(* Other procedures here *)
END Figures.
MODULE Rectangles;
IMPORT Figures;
TYPE
Rectangle* = POINTER TO RectangleDesc;
RectangleDesc* = RECORD
(Figures.FigureDesc)
x, y, w, h : INTEGER;
END;
VAR
if : Figures.Interface;
PROCEDURE New* (VAR r : Rectangle);
BEGIN
NEW(r);
Figures.Init(r, if);
END New;
PROCEDURE Draw* (f : Figure);
VAR
r : Rectangle;
BEGIN
r := f(Rectangle); (* f AS Rectangle *)
(* ... *)
END Draw;
(* Other procedures here *)
BEGIN (* Module initialisation *)
NEW(if);
if.draw := Draw;
if.clear := Clear;
if.mark := Mark;
if.move := Move;
END Rectangles.
MODULE Figures; (* Abstract module *)
TYPE
Figure* = POINTER TO FigureDesc;
Message* = RECORD END;
DrawMsg* = RECORD (Message) END;
ClearMsg* = RECORD (Message) END;
MarkMsg* = RECORD (Message) END;
MoveMsg* = RECORD (Message) dx*, dy* : INTEGER END;
Handler* = PROCEDURE (f : Figure; VAR msg : Message);
FigureDesc* = RECORD
(* Abstract *)
handle : Handler;
END;
PROCEDURE Handle* (f : Figure; VAR msg : Message);
BEGIN
f.handle(f, msg);
END Handle;
PROCEDURE Init* (f : Figure; handle : Handler);
BEGIN
f.handle := handle;
END Init;
END Figures.
MODULE Rectangles;
IMPORT Figures;
TYPE
Rectangle* = POINTER TO RectangleDesc;
RectangleDesc* = RECORD
(Figures.FigureDesc)
x, y, w, h : INTEGER;
END;
PROCEDURE Draw* (r : Rectangle);
BEGIN
(* ... *)
END Draw;
(* Other procedures here *)
PROCEDURE Handle* (f: Figure; VAR msg: Figures.Message);
VAR
r : Rectangle;
BEGIN
r := f(Rectangle);
IF msg IS Figures.DrawMsg THEN Draw(r)
ELSIF msg IS Figures.MarkMsg THEN Mark(r)
ELSIF msg IS Figures.MoveMsg THEN Move(r, msg(Figures.MoveMsg).dx, msg(Figures.MoveMsg).dy)
ELSE (* ignore *)
END
END Handle;
PROCEDURE New* (VAR r : Rectangle);
BEGIN
NEW(r);
Figures.Init(r, Handle);
END New;
END Rectangles.