Форум: "Потрепаться";
Текущий архив: 2004.12.26;
Скачать: [xml.tar.bz2];
ВнизClass Helpers (.NET) Найти похожие ветки
← →
euru © (2004-12-03 15:06) [0]Интересная возможность появилась в Delphi 2005: class helper. Только почему в Help"е написано, что используется для .NET? В Win32 тоже работает.
← →
wicked © (2004-12-03 15:08) [1]а что это такое?...
← →
euru © (2004-12-03 15:18) [2]Позволяет добавлять/изменять методы в классе без наследования.
program TestProject;
{$APPTYPE CONSOLE}
uses
SysUtils,
TestUnit in "TestUnit.pas";
var
T: TTest;
begin
T := TTest.Create();
T.Show();
T.Free();
readln;
end.
----------------------------------------------------
unit TestUnit;
interface
type
TTest = class
public
procedure Show();
end;
TTestHelper = class helper for TTest
procedure Show();
end;
implementation
procedure TTest.Show();
begin
writeln("TEST");
end;
procedure TTestHelper.Show();
begin
writeln(className(), ": TEST HELPER");
end;
end.
Результат работы:
TTest: TEST HELPER
← →
euru © (2004-12-03 15:18) [3]Позволяет добавлять/изменять методы в классе без наследования.
program TestProject;
{$APPTYPE CONSOLE}
uses
SysUtils,
TestUnit in "TestUnit.pas";
var
T: TTest;
begin
T := TTest.Create();
T.Show();
T.Free();
readln;
end.
----------------------------------------------------
unit TestUnit;
interface
type
TTest = class
public
procedure Show();
end;
TTestHelper = class helper for TTest
procedure Show();
end;
implementation
procedure TTest.Show();
begin
writeln("TEST");
end;
procedure TTestHelper.Show();
begin
writeln(className(), ": TEST HELPER");
end;
end.
Результат работы:
TTest: TEST HELPER
← →
vuk © (2004-12-03 15:22) [4]to euru © (03.12.04 15:06) :
>В Win32 тоже работает.
Не доконца оно как-то работает. Попробуйте виртуальный метод в хелпере определить...
Я про это писал здесь:
http://www.delphikingdom.com/asp/articles_forum.asp?ArticleID=1091
← →
wicked © (2004-12-03 15:24) [5]а зачем такое нужно?.... пример реальных задач, а не фича сама по себе...
← →
vuk © (2004-12-03 15:28) [6]>пример реальных задач
Например, испорльзуем сторонний класс/компонет в большом проекте. И тут пришла в голову дурная идея его расширить, например пару методов добавить. Объявляем хелпер и получаем новые методы в контексте старого класса. Ну, правда, может модуль придется в uses добавить.
← →
wicked © (2004-12-03 15:34) [7]> vuk © (03.12.04 15:28) [6]
а наследование для чего тогда?... имхо фича дублирует наследование...
единственное разумное решение - править в проекте библиотеки классов (перекрывать невиртуальные методы), если чем не устраивают... но опять таки, это решается и наследованием, и простой заменой таких библиотек на другие, которые устраивают...
еще вопрос - что будет, если к классу 2 хелпера написали, перекрывающих один и тот же метод... какой из методов будет вызван?...
← →
vuk © (2004-12-03 15:45) [8]to wicked © (03.12.04 15:34) [7]:
>а наследование для чего тогда?...
А если наследование по каким-то причинам использовать нельзя?
Пример есть в runtime библиотеке Delphi for .net С одной стороны, необходимо, чтобы TObject был корневым наследником всех классов, а с другой стороны у System.Object нет методов, которые стандартны для TObject и хотелось бы их сохранить для переносимости кода. Поэтому там сделано так:TObject = System.Object;
TObjectHelper = class helper for TObject
public
procedure Free;
function ClassType: TClass;
class function ClassName: string;
class function ClassNameIs(const Name: string): Boolean;
class function ClassParent: TClass;
class function ClassInfo: System.Type;
class function InheritsFrom(AClass: TClass): Boolean;
class function MethodAddress(const AName: string): TMethodCode;
class function MethodName(ACode: TMethodCode): string;
function FieldAddress(const AName: string): TObject;
procedure Dispatch(var Message);
end;
>что будет, если к классу 2 хелпера написали, перекрывающих один
>и тот же метод...
1. Перекрывать методы в хелперах нельзя.
2. Действует только один хелпер, который находится ближе всего к месту использования класса. Это примерно та же ситуация, что происходит, когда имеются два класса с одинаковым именем в разных модулях. Использоваться будет тот, который описан в модуле, стоящим ближе к концу списка uses.
← →
jack128 © (2004-12-03 15:45) [9]wicked © (03.12.04 15:34) [7]
а наследование для чего тогда?...
а если от того класса уже есть наследники? Тогда придется их тоже менять.
← →
wicked © (2004-12-03 15:53) [10]> vuk © (03.12.04 15:45) [8]
а чем хуже было бы просто наследовать TObject от System.Object?... эффект, имхо, тот же, и подпорок не надо...
> jack128 © (03.12.04 15:45) [9]
и если я определю другой метод для класса-предка, то он будет вызван в наследнике?... бррр...
> всем
может я и буду слишком категоричным, но это похоже на индульгенцию всем тем, кто не утруждает себя продуманной иерархией классов... лечение перелома пластырем... :(
← →
jack128 © (2004-12-03 15:58) [11]wicked © (03.12.04 15:53) [10]
эффект, имхо, тот же, и подпорок не надо...
тогда методы TObject будет недоступны нем классам, которые наследуются неосредственно от System.Object
wicked © (03.12.04 15:53) [10]
может я и буду слишком категоричным, но это похоже на индульгенцию всем тем, кто не утруждает себя продуманной иерархией классов... лечение перелома пластырем... :(
Как сказать. В душе я с тобой полностью согласен, но на практике это будет очень полезная вещь. см тот же tobject. без Helper"ов согласование VCL и Forms было бы практически невозможно.
← →
vuk © (2004-12-03 15:58) [12]>эффект, имхо, тот же, и подпорок не надо...
В том-то и дело, что эффект как-раз не тот же, т.к. у System.object уже есть куча наследников и если TObject не будет совпадать с System.Object, все классы, порожденные в delphi будут формировать отдельную иерархию, а при работе со всеми классами .net framework нельзя будет использовать методы TObject. При использовании хелперов проблема исчезает.
← →
euru © (2004-12-03 16:02) [13]С наследованием
program TestProject;
{$APPTYPE CONSOLE}
uses
SysUtils,
TestUnit in "TestUnit.pas";
var
T: TTest;
begin
T := TTest.Create();
T.Show();
T.Free();
T := TDerivedTest.Create();
T.Show();
T.Free();
readln;
end.
-----------------------------------------------------
unit TestUnit;
interface
type
TTest = class
public
procedure Show();
end;
TDerivedTest = class(Ttest)
procedure Show();
end;
TTestHelper = class helper for TTest
procedure Show();
end;
implementation
procedure TTest.Show();
begin
writeln("TEST");
end;
procedure TDerivedTest.Show();
begin
writeln("DERIVED TEST");
end;
procedure TTestHelper.Show();
begin
writeln(className(), ": TEST HELPER");
end;
end.
Результат работы:
TTest: TEST HELPER
TDerivedTest: TEST HELPER
← →
Игорь Шевченко © (2004-12-03 16:05) [14]vuk © (03.12.04 15:58) [12]
<offtopic>
Почту глянь :)
</offtopic>
← →
wicked © (2004-12-03 16:09) [15]> vuk © (03.12.04 15:58) [12]
> В том-то и дело, что эффект как-раз не тот же, т.к. у System.object
> уже есть куча наследников и если TObject не будет совпадать
> с System.Object, все классы, порожденные в delphi будут
> формировать отдельную иерархию, а при работе со всеми классами
> .net framework нельзя будет использовать методы TObject.
> При использовании хелперов проблема исчезает.
они и так формируют отдельныю иерархию...
я бы согласовывал их, например, агрегацией .NET классов внутрь соответствующих VCL классов... то есть, было бы возможно существование VCL и VCL.NET с единым программным интерфейсом...
хотя, тут дальше идти не буду, поскольку не знаю иерархии .net классов....
← →
wicked © (2004-12-03 16:10) [16]> wicked © (03.12.04 16:09) [15]
> агрегацией .NET классов
агрегацией обьектов .NET классов....
← →
vuk © (2004-12-03 16:11) [17]>они и так формируют отдельныю иерархию...
Нет, они являются наследниками system.object, а не класса, порожденного от system.object. Разницу чувствуете?
← →
wicked © (2004-12-03 16:20) [18]> vuk © (03.12.04 16:11) [17]
> Разницу чувствуете?
нет, если честно... какую разницу вы вкладываете между терминами "наследник" и "класс, порожденный от"?... имхо, разницы нету, ultimate ancestor для них был бы один - system.object... или я не прав?...
← →
vuk © (2004-12-03 16:38) [19]Положение номер раз. Все классы в Delphi являются наследниками TObject.
Положение номер два. Все классы .net являются наследниками system.object.
Если TObject будет наследником system.object, то мы не сможем породить наследника от класса, находящегося где-то в иерархии классов .net. Но ведь хочется, правда? :o) Поэтому сделано так, что System.object и TObject - это один класс, а не два разных. А дополнительные методы "навешены" на system.object при помощи хелпера.
← →
wicked © (2004-12-03 16:43) [20]> vuk © (03.12.04 16:38) [19]
> Если TObject будет наследником system.object, то мы не сможем
> породить наследника от класса, находящегося где-то в иерархии
> классов .net.
а почему не сможем?.... (не придираюсь, просто не вижу причин не-возможности так сделать)
и еще такой вопрос: что будет, если я у себя в проекте захочу создать хелпер для TObject или какого-либо его наследника?...
← →
REA (2004-12-03 16:46) [21]Иногда нужно на готовые классы (или компоненты) навесить некую общую функциональность (нет возможности унаследовать от нужного общего предка). Или классы унаследованные от разных предков должны обеспечить некую общую функцию.
Я это раньше делал через интерфейсы. Если есть способ сделать это на уровне языка, то возможно это хорошо.
← →
vuk © (2004-12-03 16:49) [22]to wicked © (03.12.04 16:43) [20]:
>а почему не сможем?....
Есть иерархии:
A->B->C
и
A->D->E
Как сделать класс одновременно наследником C и E? Множественного наследования нет.
>и еще такой вопрос: что будет, если я у себя в проекте захочу
>создать хелпер для TObject или какого-либо его наследника?...
Да на здоровье!
← →
wicked © (2004-12-03 16:53) [23]> vuk © (03.12.04 16:49) [22]
спасибо.... :)
← →
euru © (2004-12-03 16:57) [24]>vuk © (03.12.04 15:22) [4]
Если в хелпере объявить виртуальный класс, то ищется какой-то стандартный тип TObjectHelper. Может нужно какой-то юнит указать?
> wicked ©
А что именно вас так смущает в хелперах?
← →
vuk © (2004-12-03 17:01) [25]to euru © (03.12.04 16:57) [24]:
Дублирую сюда с королевства.----------------------------------
С хелперами возникли непонятки. При попытке определить в хелпере виртуальный метод сначала выругался компилятор.[Error] Project2.dpr(20): E2003 Undeclared identifier: "QueryInterface"
[Error] Project2.dpr(20): E2003 Undeclared identifier: "_AddRef"
[Error] Project2.dpr(20): E2003 Undeclared identifier: "_Release"
Хотя никаких интерфейсов я даже не трогал. После того, как в хелпер были добавлены эти функции компиляция прошла успешно, но работать от этого не начало, т.к. стала появляться ошибка Access Violation. При рассмотрении ассемблерного кода выяснилось, что вызывается встроенная функция GetHelperIntf, и после этого делается попытка какого-то вызова. Но GetHelperIntf возвращает nil всегда, и поэтому возникает Access Violation. Что характерно, до появления виртуального метода никаких методов интерфейса не требовалось и все работало замечательным образом.program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
type
TestClass = class
end;
TestClassHelper = class helper for TestClass
procedure Test;
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
procedure proba; virtual;
end;
{ TestClassHelper }
procedure TestClassHelper.proba;
begin
writeln(ClassName);
end;
function TestClassHelper.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
end;
function TestClassHelper._AddRef: Integer;
begin
end;
function TestClassHelper._Release: Integer;
begin
end;
procedure TestClassHelper.Test;
begin
writeln("test");
end;
var
c : TestClass;
begin
c := TestClass.Create;
c.proba;
readln;
end.
← →
euru © (2004-12-03 17:13) [26]>vuk © (03.12.04 17:01) [25]
Текст на Королевстве я прочёл. Просто когда в хелпер добавляется виртуальный метод, среда сообщает, что она пытается найти тип TObjectHelper. Возможно, надо указать юнит, в котором он описан, а хелпер объявить следующим образом:
TestClassHelper = class helper (TObjectHelper) for TestClass
← →
euru © (2004-12-03 18:27) [27]Кстати, уважаемый vuk, примерно год назад мы с вами дискутировали примерно по такой же теме. Я ещё в кладовку выложил реализацию для Delphi 7, правда не хелперов, а более общего подхода. Хотя я всё это до ума так и не довёл.
Борландовские хелперы как раз реализовали только то, что было сделано мной. Функциональность практически один-в-один: у них вылезают уши IInterface, и у меня он используется; у них нельзя в хелпере объявлять поля, и у меня (просто не было реализовано). Хотя у них есть преимущество: возможность ввести в Delphi ключевое слово.
Может быть, они периодически заглядывают на этот сайт и, так сказать, воспользовались моим решением? (шутка)
Хотя у меня реализация гибче была. Хелпер можно было связывать в ран-тайме. И не только с классом, но и с отдельным объектом класса.
← →
vuk © (2004-12-03 18:36) [28]to euru:
>Просто когда в хелпер добавляется виртуальный метод, среда
>сообщает, что она пытается найти тип TObjectHelper.
А мне ничего такого не сказали. Просто сообщили об отсутствии методов. Все в конце концов скомпилировалось. Но легче не стало.
>Кстати, уважаемый vuk, примерно год назад мы с вами
>дискутировали примерно по такой же теме.
Что-то было, подробностей уже не помню, увы. Сначала мне не до того было, потом забыл. Может, если пороюсь по архивам, что и найду...
← →
euru © (2004-12-03 18:51) [29]>vuk © (03.12.04 18:36) [28]
Я был несколько неправ. Сообщение об ошибке содержится в узле Errors окна Structure независимо от виртуальности метода в хелпере:
Failed to find standard type "TObjectHelper" at line ..."
Если найдёте, сообщите. А то и кладовка, оказывается, закрыта.
← →
euru © (2004-12-06 14:16) [30]А вот перегрузки операторов для Win32 нет, что странно. Ведь было же уже готовое решение для Delphi7. Оставалось только внедрить его в язык.
Или я просто не умею их готовить?
← →
vuk © (2004-12-07 23:04) [31]Описание бага с хелперами отправлено в QualityCentral. Если кого интересует, то id=9782
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.12.26;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.039 c