Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 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.047 c
1-1103013863
R
2004-12-14 11:44
2004.12.26
Округление до целого


1-1102710065
Руслана
2004-12-10 23:21
2004.12.26
Подскажите как при вызове SaveDialog сделать чтобы в качестве


3-1101817727
Shuma
2004-11-30 15:28
2004.12.26
Ошибка при добавлении картинки в базу


8-1096484028
X-RayMan
2004-09-29 22:53
2004.12.26
OpenGL


11-1084435973
dimon1979
2004-05-13 12:12
2004.12.26
KOL-компоненты и тип PControl





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский