- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
type
// смотрите, как не надо делать и почему придумали ООП
TProc = procedure;
TGoProc = function: boolean;
TSizeProc = function: integer;
TGetConfigProc = function: string;
TApplyConfigProc = procedure(SM: PStringMap);
TDeviceProc = record
InitControls: TProc;
MoveControls: TProc;
Go: TGoProc;
MaxH, MinH: TSizeProc;
GetConfig: TGetConfigProc;
ApplyConfig: TApplyConfigProc;
end;
const
DeviceProcs: array [TDevice] of TDeviceProc = (
(InitControls: ETR.InitControls; MoveControls: ETR.MoveControls; Go: ETR.Go; MaxH: ETR.MaxH; MinH: ETR.MinH; GetConfig: ETR.GetConfig; ApplyConfig: ETR.ApplyConfig),
(InitControls: TS_NSH.InitControls; MoveControls: TS_NSH.MoveControls; Go: TS_NSH.Go; MaxH: TS_NSH.MaxH; MinH: TS_NSH.MinH; GetConfig: TS_NSH.GetConfig; ApplyConfig: TS_NSH.ApplyConfig),
(InitControls: TS_IND.InitControls; MoveControls: TS_IND.MoveControls; Go: TS_IND.Go; MaxH: TS_IND.MaxH; MinH: TS_IND.MinH; GetConfig: TS_IND.GetConfig; ApplyConfig: TS_IND.ApplyConfig),
(InitControls: TP_NSH.InitControls; MoveControls: TP_NSH.MoveControls; Go: TP_NSH.Go; MaxH: TP_NSH.MaxH; MinH: TP_NSH.MinH; GetConfig: TP_NSH.GetConfig; ApplyConfig: TP_NSH.ApplyConfig),
(InitControls: TP_IND.InitControls; MoveControls: TP_IND.MoveControls; Go: TP_IND.Go; MaxH: TP_IND.MaxH; MinH: TP_IND.MinH; GetConfig: TP_IND.GetConfig; ApplyConfig: TP_IND.ApplyConfig)
);
Вот до чего доводит ненависть к ООП.
ОПП - это хорошо, ООП не надо ненавидеть.
Просто необходимо забывать, что есть тот 1%, где без него можно прекрасно обойтись
нет, этот код не попадает в тот 1%
каждой ТДевице по ТКинду, на 8 марта.
по понятности и привычности - Ваш код заметно уступает виртуальным методам.
по производительности:
2 лишних (по сравнению с обычным вызовом обычной процедуры) обращения к памяти (1 mov и 1 в call) против 1 лишнего (1 call) - оно того действительно стоит?
Если уж так важна производительность...
вызов функции сам по себе содержит много обращений к памяти - стек, переменные... тогда уж лучше те функции написать на асме - больше выиграете. И неочевидной будет не логика всей программы, а отдельных функций опять же выиграш...
Хорошо, покажу кое-что, слабонервным не смотреть.
type test1 = class(TObject)
procedure foo(); virtual;
end;
type test2 = class(test1)
procedure foo(); override;
end;
var t: test1;
...
t := test2.Create();
t.foo(); // вот это развернется в:
mov eax, [<адрес t>] // указатель на экземпляр класса
mov edx, [eax] // получение дексриптора класса
call [edx + <константа, определяемая компилятором>]
если убрать virtual/override то будет:
mov eax, [<адрес t>] // указатель на экземпляр класса
call [<адрес процедуры>]
вот dynamic использовать не нужно.
Весь VCL на них сделан, увы.
В интерфейсных компонентах не имеет большого значения. А там где нужна скорость - ну есть много решений - если уж ничего не нравится - ручками сделайте... изобретательство велосипедов конечно, но куда ж деваться :(
Вообще, изначально вопрос стоял про приведенный здесь код.
работать он будет. будет быстро, если руки не кривые.
В производительности разница будет не заметена по сравнению с virtual/override, но последнее привычнее - существенно, когда будете код передавать кому-то.
Что стоит использовать - решать автору.
MY
GOD
!!!
еще один камень в стан Ботланда
Virtual and dynamic methods are semantically equivalent. They differ only in the implementation of method-call dispatching at runtime. Virtual methods optimize for speed, while dynamic methods optimize for code size.
(с) Delphi help, поиск в указателе Dynamic methods, последний абзац...
покажите мне реализацию шедулера на джс)
остальное тоже можно найти