Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];

Вниз

Вопрос по внутренней организации классов в Delphi   Найти похожие ветки 

 
Тимохов   (2003-10-30 13:16) [0]

Опишу проблему, которую мне надо решить.
Допустим есть класс TClass1 (заметьте, что про объекты этого класса речь пока не идет). Я хочу в некоторой структуре данных сохранить ссылку на статический (т.е. не виртуальный) метод этого класса. И в дальнейшем, когда появится объект этого класса, то этот метод вызвать. Так называемый procedural тип здесь не подходит (т.е. тип, которым сделаны ивенты), т.к. для этого типа необходимо существования объекта, т.е. знание класса недостаточно. Поясню задачу схематическим примером. Очевидно, что в примере есть синтаксические ошибки, но все же его приведу, чтобы, что лучше пояснить вопрос

type
TClass1 = class
fA: String;
procedure SomeMethod(A: String)
end

procedure TClass1.SomeMethod(A: String)
begin
fA := A;
end;

var
fPointerToMethod: Pointer;
fObj: TClass1;
begin
// 1. Запоминаем ссылку на метод TClass1.SomeMethod
fPointerToMethod := TClass1.SomeMethod;
// 2. Создаем объект класса TClass1
fObj := TClass1.Create;
// 3. Вызываем метод
fObj.fPointerToMethod("a");
// ЗАМЕЧУ, что все три пункта сильно разнесены во времени.
// Это в примере они идут радом. В программе ини должны
// идти в разных местах
end;

Очевидно, что для реализации задачи нужно хорошо знать внутреннюю организацию классов и объектов. Я, к сожалению, такими знаниями не обладаю.

Какие будут мысли?


 
Романов Р.В.   (2003-10-30 13:23) [1]

Теперь объяси для чего это нужно


 
VMcL   (2003-10-30 13:28) [2]

>Тимохов (30.10.03 13:16)

см. record TMethod


 
ZeroDivide   (2003-10-30 13:30) [3]

Очевидно, что в примере есть синтаксические ошибки
Очевидно, ошибки есть и в понимании ООП


 
Reindeer Moss Eater   (2003-10-30 13:30) [4]

А зачем сохранять ссылку на статический метод? (на виртуальный я бы еще понял)


 
Тимохов   (2003-10-30 13:31) [5]

Объясняю.
У нас в конторе долгое время пользовались MSXML parser. Пришло время когда он нас перестал удовлетворять по скорости работы и по занимаемой памяти. На писали свой почти-аналог. Убрали ненужное, добавили нужное. Такой движок нас очень удовлетворяет - работает существенно быстрее чем MSXML. Теперь занимаемся дальнейшей оптимизацией. Атрибуты мы храним пока в списке variant"ов, что при больших объемах (порядка 5 000 000 тегов) неоптимально. Хочется зделать так, чтобы в описании схемы для каждого атрибута указывать методы из класса тега (для каждого тега у нас можно делать дельфовый класс), которые будут отвечать за установку и получения значения атрибута. Каждый класс может хранить свои атрибуты в private переменных именно того типа, который заявлен, как тип атрибута. Т.е. метода такая:
1. Я говорю, что хочу получить значение атрибута "Name" тега "Font".
2. Движок лезет в объект указанного тэга, в его схеме находит атрибут с именем "Name", узнает какие методы отвечают за получение и установку указанно атрибута. И вызывает метод получения атрибута
3. Метод вызывается у объекта "Font". Метод берем private переменную fName и возвращает ее.

Все. Понятно?


 
Тимохов   (2003-10-30 13:33) [6]

То ZeroDivide. Фу... как некультурно. В пониматии OOП к сожадению ошибок нет. Если бы были, давно бы решил задачу. Выше приведено описание зачем это нужно.


 
Reindeer Moss Eater   (2003-10-30 13:36) [7]

Так называемый procedural тип здесь не подходит (т.е. тип, которым сделаны ивенты), т.к. для этого типа необходимо существования объекта, т.е. знание класса недостаточно.

А как статический-то метод может помочь если нет экземпляра?


 
Reindeer Moss Eater   (2003-10-30 13:36) [8]

Это же D, а не Java


 
alex_***   (2003-10-30 13:37) [9]

Так можно вызывать только статические методы классов (не имеют доступ к полям класса) , по кр. мере в С++ я делал. А так как этот метод получает доступ к экземпляру объекта : fA := A, то работать с этим методом можно только в контексте экземпляра объекта, потому как ссылка на fA хранится в экземпляре в стеке.


 
Тимохов   (2003-10-30 13:40) [10]

То Reindeer Moss Eater.
----------------------
Если смотреть asm, сгенеренных по коду дельфи, то видно, что статические методы вызываются просто не как методы, а даже как независимые функции. Т.е. вызов идет по абсотютному адресу в памяти. При этом один из параметров это ссылка на объект.

Просто нужно сделать так, чтобы сохранить информацию о том методе, который нужно вызвать, когда экземпляр появится.

Эта задача точно должна решаться, просто мне не хватает знаний, как дельфи все это оргаризовавает.

То VMcL
------
Спасибо. Буду ботать.


 
Reindeer Moss Eater   (2003-10-30 13:44) [11]

Т.е. вызов идет по абсотютному адресу в памяти.

Все имеет свой адрес в памяти и все можно вызвать по абсолютному адресу. Только говорить об этом вне контекста конкретного языка бессмыслено.
А у тебя Delphi.


 
Radionov Alexey   (2003-10-30 13:48) [12]

А для published вот что есть в TObject:
class function MethodAddress(const Name: ShortString): Pointer;


 
VMcL   (2003-10-30 13:52) [13]

>Тимохов (30.10.03 13:40) [10]

Вот пример для понимания принципа:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
public
procedure Test(A: Integer);
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Test(A: Integer);
begin
ShowMessage("Ha-ha: " + IntToStr(A));
end;

procedure TForm1.FormCreate(Sender: TObject);
type
TTest = procedure (A: Integer) of object;
var
CurTest: TTest;
begin
TMethod(CurTest).Code := @TForm1.Test;
// ...
TMethod(CurTest).Data := Self; // e. g.
// ...
CurTest(5);
// ...
PostQuitMessage(0); // This is a test
end;

end.


 
Тимохов   (2003-10-30 13:56) [14]

То VMcL.
Огромное тебе спасибо (и остальным тоже).
Я уже написал пример, очень похож на твой. Значти я все понял правильно.

На самом деле, это первый раз когда мне на форуме (не только на этом) ответили вобщем-то на нетривиальный вопрос.

Всем спасибо.


 
Тимохов   (2003-10-30 14:03) [15]

Все-таки нетривиальное это дело - написание мануалов.

В дельфи написано, что переменная типа method pointer на самом деле это два значения - ссылка на метод и ссылка на объект.

Но в мануале нет ни слова о TMethod. Вполне могли бы это написать, т.к. сами этим активно пользуются в TReader.


 
Polevi   (2003-10-30 14:31) [16]

я бы сделал с пропертями


 
Тимохов   (2003-10-30 14:32) [17]

То Polevi.

Что значит "с пропертями"?


 
Vuk   (2003-10-30 14:35) [18]

to Тимохов:
>Что значит "с пропертями"?
Я так понимаю, что имеются в виду published свойства с определенными именами.


 
Smithson   (2003-10-30 15:18) [19]

Ну а что мешает этот конкретный статический метод сделать вообще не методом?

// Описание
Procedure StatMethod(Obj: TYourBasedObject, Params: ...)

// Реализация
Procedure StatMethod(Obj: TYourBasedObject, Params: ...)
Begin
Obj.A := Params;
End;

// Вызов
begin
...
StatMethod(YourObject, "Sssssssss");
end;


?


 
Тимохов   (2003-10-30 15:29) [20]

То Smithson.
Такой метод мы уже реализовали. Он нас не в полне удовлетворяет.

На самом деле мне уже ответили, как мне решить эту проблему. Теперь передо мной открывается хорошая перспектива: с одной стороны я могу пользоваться пропертями, с другой стороны все проперти будут объеденены в некотором списке, и я могу с ними делать какие-то массовые операции, например, делать клон (копию) объекта без явного описания какие поля нужно копировать или запись в файл.


 
Polevi   (2003-10-30 16:14) [21]

информация о published свойствах доступна через RTTI - написать процедуру сериализации объекта в xml конверт и десериализации его - очень просто. не нужно "явного описания какие поля нужно копировать", с методами мне кажется както кривовато, IMHO



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.055 c
14-41952
Ш-К
2003-10-20 13:15
2003.11.13
Delphi&1C


14-41907
Study
2003-10-21 13:39
2003.11.13
nmsmtp


1-41705
mc_duck
2003-11-03 20:06
2003.11.13
Окно с секретом


1-41657
Rimas
2003-10-25 14:32
2003.11.13
русский help


1-41525
Stas
2003-10-28 11:07
2003.11.13
TCanvas





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский