Когда-то Акжан Абдулин это уже писал... Делюсь... Я лет 8-мь это уже использую... шаблоны в Delphi 7: TList.intf: TList = class(Parent) Add(a: ItemType); Insert(i: Integer; a: ItemType); Sort(); end; .. TList.impl TList.Sort() .. CompareItems(a, b) : Integer; .. Parent = TObject; ItemType = integer; {$include TList.intf} TIntList = class(TList) .. CompareItems(a, b : Integer) : Integer; begin Result := a - b; end; {$Include TList.impl}
-------------------------------------------------------------------
Пример:
------------------------------------------------------------------------------------------------
ИТОГО:
stack.imp.pas:
{$IfNDef Stack_imp} {$Define Stack_imp} ItemsHolder = array of _ItemType_; _Stack_ = {mixin} class(TObject) private // private fields f_Items : ItemsHolder; public // public methods procedure Push(const anItem: _ItemType_); function Pop: _ItemType_; end;//_Stack_ {$Else Stack_imp} // start class _Stack_ procedure _Stack_.Push(const anItem: _ItemType_); var l_L : Integer; begin l_L := Length(f_Items); SetLength(f_Items, l_L + 1); f_Items[l_L] := anItem; end;//_Stack_.Push function _Stack_.Pop: _ItemType_; var l_L : Integer; begin l_L := Length(f_Items) - 1; Result := f_Items[l_L]; SetLength(f_Items, l_L); end;//_Stack_.Pop {$EndIf Stack_imp}
----------------------------------------------------------------------------------------------
IntStack.pas:
unit IntStack; interface type _ItemType_ = Integer; {$Include Stack.imp.pas} TIntStack = class(_Stack_) end;//TIntStack implementation {$Include Stack.imp.pas} end.
----------------------------------------------------------------------------------------------
StringStack.pas:
unit StringStack; interface type _ItemType_ = AnsiString; {$Include Stack.imp.pas} TStringStack = class(_Stack_) end;//TStringStack implementation {$Include Stack.imp.pas} end.
!!!! Понятно, что ДИНАМИЧЕСКИЙ МАССИВ тут используется просто для примера. Понятно, что было можно ввести PItemType = ^_ItemType_ и оперировать указателями и GetMem. Но это усложнило бы пример.
И понятно, что тут нету проверки граничных условий.
Попробуйте. И может быть - вам понравится.
Ну а про настоящие generic'и читаем тут - http://keeper89.blogspot.ru/2011/07/delphi.html
А одна из моих реализаций данной идеи описана тут - http://18delphi.blogspot.com/2013/07/2_18.html
Ничего не понял, а можно исходник с примером?
ОтветитьУдалитьТак это исходник и есть :-)
ОтветитьУдалитьодин файл:
TList.intf:
TList = class(Parent)
Add(a: ItemType);
Insert(i: Integer; a: ItemType);
Sort();
end;
второй файл:
TList.impl:
TList.Sort()
- тут реализуем Sort используя CompareItems (которую определим потом)
TList.Insert(i: Integer; a: ItemType);
- тут реализуем Insert используя ItemType, который определим потом
третий файл:
IntList.pas:
interface
Parent = TObject;
ItemType = integer;
// - определили ItemType
{$include TList.intf}
// - включили интерфейс списка
TIntList = class(TList)
..
implementation
CompareItems(a, b : Integer) : Integer;
// - определили функцию сравнения
begin
Result := a - b;
end;
{$Include TList.impl}
// - включили реализацию списка
Ща сделаю компилируемый пример.
ОтветитьУдалитьДобавил пример в тело поста.
ОтветитьУдалитьЗавтра продолжу немножко занудствовать про TDD и нарисую два DUnit-теста к получившимся классам.
ОтветитьУдалитьА также немножко позанудствую про примеси и нарисую как сделать не только TIntStack, Но и TPesistentIntStack и TComponentedIntStack.
Инетересно, но вот форматера кода явно не хватает/ Да и почему то комнтарий лучше воспринимается чем сама статья. Буду ждать продолжения.
ОтветитьУдалитькомпилируемый пример,я думал что это будет архивчик с проектом, а так он не компилируемый вовсе :)
ОтветитьУдалитьИ в каком месте он не компилируемый?
ОтветитьУдалитьЯ прямо в восторге, век живи век учись.
ОтветитьУдалитьА теперь компилируемый, раньше ссылка была на файл *.impl.pas, а сам файл создавался просто *.impl и была куча странных коментов которые взрывали мозг, теперь лучше. Спасибо за пост.
Присоединяюсь по поводу восторгов, это я писал первый комментарий, теперь все понятно, спасибо.
ОтветитьУдалитьЗ.Ы. Не компилироваться может потому что inc файл не нужно включать в проект. Лучше было бы его вообще сделать с другим расширением, чтоб не путаться.
Про расширение - согласен. Но тогда подсветка синтаксиса по-умолчанию не работает. Надо настраивать.
ОтветитьУдалитьФайлы *.imp.pas - действительно НЕ НАДО включать в проект.
По поводу восторгов - ложка дёгтя. В "шаблонах" breakpoint'ы не ставятся. Оно в общем и понятно - почему. Потому, что компилятор делает несколько копий кода. А отладчик не настолько умён - чтобы с ними разобраться. Но есть техники, которые позволяют это обойти. Позже - расскажу как.
Вот продолжение - http://18delphi.blogspot.com/2013/03/blog-post_29.html
ОтветитьУдалитькстати в Delphi 2010 брекпоинты очень даже хорошо ставятся и прекрасно работают :)
ОтветитьУдалитьВезёт...
УдалитьНу тут варианта - два. Либо они это доделали. Во что мне лично, при всём моём уважении, не очень вериться.
Либо у тебя примесь примешивается (инстанцируется) РОВНО ОДИН раз. В это мне вериться - больше.
может дело в расширении файла? inc vs pas?
Удалитья проверял на примере UTF8LengthLimiter - inc инстанцируется два раза; одна точка останова отрабатывает сразу для обоих инстанций - вот это не очень удобно..
15 лет жили без всяких там дженериков, зачем всё усложнять?
ОтветитьУдалитьКак только Borland развалился, так и начались приколы...
Сначала внешний вид среды изуродовали и слепили все окна в кучу, потом unicode, потом наконец-то склепали модуль RTTI.pas , но и туда влепили свои дженерики,- вот нельзя было без них?
Как по мне, то пусть код будет больше, но проще для понимания.
Я с 7 делфи так и не перелез ещё,хотя уже 10,4 потрогал.
УдалитьНа моём ноуте это неповоротливая медленная корова :)
Что можете посоветовать поставить в промежутке от 7 до 10?
Желательно пошустрее версию :).
А то самому переписывать из новых версий в седьмую надоело...Всякие там векторы и прочее.
Занимаюсь последнее время изображениями и стало чувствоваться нехватка SSE и AVX в компиляторе при работе с миллионами векторов.
"Я с 7 делфи так и не перелез ещё,хотя уже 10,4 потрогал"
УдалитьЯ практически тоже... Так в основном и остался на Delpi 7.