Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.12.26;
Скачать: CL | DM;

Вниз

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;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.041 c
3-1101812052
Eugene1501
2004-11-30 13:54
2004.12.26
Ошибка при попытке открыть dbf


1-1102924866
Ольга
2004-12-13 11:01
2004.12.26
Странные символы &amp; в PopupMenu


1-1102668654
msm
2004-12-10 11:50
2004.12.26
Проблема с TDateTime


4-1099992720
syte_ser78
2004-11-09 12:32
2004.12.26
версия файла


14-1102473842
Думкин
2004-12-08 05:44
2004.12.26
С днем рождения! 8 декабря