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

Вниз

Интерфейсы и классовые функции   Найти похожие ветки 

 
REA ©   (2004-04-14 16:35) [0]

Нужно получить информацию о классе, до его создания (аналог ClassName). Известно, что класс поддерживает некий интерфейс, но получить его без создания класса не удается. Явно преобразовывать класс к типу нельзя. Получить ссылку на классовый метод в виде Pointer через MethodAddress удается, но корректно преобразовать и вызвать тоже не получается.


 
Тимохов ©   (2004-04-14 16:38) [1]


> REA ©   (14.04.04 16:35)  

вы думаете реально что-то тут сказать?
вы конечно сильно потрудились задавая вопрос...


 
REA ©   (2004-04-14 16:46) [2]

Хм. Попробую изложить ииначе:
Требуется получить информацию о классе (через классовую функцию).
Сам класс неизвестного типа - т.е. не унаследован от общего предка и заранее неизвестно есть у него эта функция или нет.
Приходит в голову два метода:
1) реализовать некий интерфейс и, если он поддерживается, то вызвать его функцию.
2) Получить указатель на published метод по его имени и вызвать.

В первом случае я не смог получить интерфейс (или метод интерфейса) без создания экземпляра класса, а во втором не знаю как преобразовать укзатель к Class Function заданного типа.


 
Тимохов ©   (2004-04-14 16:50) [3]


> В первом случае я не смог получить интерфейс (или метод
> интерфейса) без создания экземпляра класса

логично - интерфейс сам по себе не живет - только над объектом.

Разрешите спросить - откуда такая задача?

Не пойму фразу "Требуется получить информацию о классе (через классовую функцию)."

Что значит "через классовую функцию"?

Может еще попробуете углубиться в  объяснениях?


 
Гаврила   (2004-04-14 16:53) [4]

Ну так нужно значит отнаследовать класс от общего предка, и сделать виртуальную классовую функцию.


 
REA ©   (2004-04-14 16:53) [5]

>логично - интерфейс сам по себе не живет - только над объектом.

Ну почему - можно получить AClass.GetInterfaceEntry(IID), только потом еще придется разбирать самому.

>Что значит "через классовую функцию"?

TSomeClass = Class
Published
 Class Function GetSomeClassInfo: String;
End;


 
VMcL ©   (2004-04-14 16:54) [6]

>>REA ©  (14.04.04 16:46) [2]

Почему экземпляр класса нельзя создавать?


 
WebErr ©   (2004-04-14 16:54) [7]


> Тимохов ©   (14.04.04 16:50) [3]

:)
Не издевайтесь!!! :))))


 
REA ©   (2004-04-14 16:55) [8]

>Ну так нужно значит отнаследовать класс от общего предка, и сделать виртуальную классовую функцию.

Да вот как раз и не получается - мне нужно добавить свою функциональность к готовым компонентам. Множественного наследования тут нет.


 
REA ©   (2004-04-14 16:56) [9]

>Почему экземпляр класса нельзя создавать?

Нет смысла - каждый раз создавать компонент, чтобы получить ClassName, например это слишком.


 
VMcL ©   (2004-04-14 17:01) [10]

>>REA ©  (14.04.04 16:56) [9]

Можно в структуре, которую возвращает классовая фукция, передавать GUID(ы) поддерж. интерфейса(ов). Ну и соответсвенно у всех необходимых интерфейсов они (GUID) должны быть.


 
Тимохов ©   (2004-04-14 17:05) [11]


> Нет смысла - каждый раз создавать компонент, чтобы получить
> ClassName, например это слишком.


Что-то вы странное говорите.
"Нет смысла", значит вы можете создать, но считаете это не нужным.
Если вы можете создать, то значит вы знаете класс, а если знаете класс, то вы можете у класса брать classname (он же тоже классовый метод).

или я что-то не понимаю.


 
default ©   (2004-04-14 17:06) [12]

"Получить ссылку на классовый метод в виде Pointer через MethodAddress удается, но корректно преобразовать и вызвать тоже не получается"
вот как это делается
...

TMyObj = class
published
  class procedure PutHello;
end;

TProc = procedure;

...

class procedure TMyObj.PutHello;
begin
Form1.Caption := "Hello"
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
TProc(TMyObj.MethodAddress("PutHello"))
end;

...


 
VMcL ©   (2004-04-14 17:08) [13]

>>default ©  (14.04.04 17:06) [12]

Вызывать метод, как обычную процедуру - оригинально.


 
default ©   (2004-04-14 17:13) [14]

VMcL ©   (14.04.04 17:08) [13]
передаётся указатель на код метода?что же делать?!)))


 
Юрий Зотов ©   (2004-04-14 17:13) [15]

Не вижу проблемы.

class function ClassName: ShortString;

Это классовый метод, дает имя класса (то есть - полную информацию о классе), для его вызова создавать экземляр класса не требуется и она есть у TObject (то есть - у ВСЕХ классов).

Что же еще нужно-то?


 
default ©   (2004-04-14 17:19) [16]

VMcL ©   (14.04.04 17:08) [13]
штука в том что по умолчанию классовому методe указатель на класс передаётся через регистр(EAX)(не через стек)
поэтому мы можем вызвать его и как процедуру(если не исп-ся EAX)


 
VMcL ©   (2004-04-14 17:21) [17]

>>default ©  (14.04.04 17:19) [16]

Можно в носу опасной бритвой ковыряться. Ну и что?


 
Тимохов ©   (2004-04-14 17:23) [18]


> VMcL ©   (14.04.04 17:21) [17]
> >>default ©  (14.04.04 17:19) [16]
>
> Можно в носу опасной бритвой ковыряться. Ну и что?


Ответ настоящего светлого!!! :))))))

Согласен с VMcL - опасно это. Лучше так не делать.

Да и вообще какое это имеет отношение к вопросу автора.


 
default ©   (2004-04-14 17:23) [19]

VMcL ©   (14.04.04 17:21) [17]
я ничего не навязываю)это было пояснение к возмущению


 
default ©   (2004-04-14 17:25) [20]

пугливые однако)


 
REA ©   (2004-04-14 17:35) [21]

2ЮЗотов:
>Что же еще нужно-то?
Нужно как раз не ClassName, а другой метод. Это я для примера его употребил.

2default> Да так и делал - выдает AV


 
Тимохов ©   (2004-04-14 17:36) [22]


> я для примера его употребил.

плохой значит пример...

Все-таки ваша задача не ясна до конца (прочел весь топик).
Можете по пунктам расписать, что нужно?


 
VMcL ©   (2004-04-14 17:38) [23]

>>default ©  (14.04.04 17:25) [20]

Вопрос не в пугливости. Возможно придет время и нужно будет использовать Self в классовом методе, со временем особенности кода уже подзабудутся, а в EAX пурга полнейшая.


 
Юрий Зотов ©   (2004-04-14 17:38) [24]

> REA ©   (14.04.04 17:35) [21]

Чем конкретно не устраивает ClassName?


 
default ©   (2004-04-14 17:41) [25]

REA ©   (14.04.04 17:35) [21]
именно в моём коде? модель вызова register?
VMcL ©   (14.04.04 17:38) [23]
согласен, я бы тоже так вряд ли стал делать в реальном проекте...только если бы скорость ОЧЕНЬ важна была


 
REA ©   (2004-04-14 17:44) [26]

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

TMyPanel = Class(TPanel)
Published
 Class Function FriendlyComponentName: String;
End;

У меня есть список TClassList с этими объектами. Нужно получить их названия. Типа такого:

If HaveFriendlyName(List[i]) Then MyName := GetName(List[i]);


 
REA ©   (2004-04-14 17:45) [27]

>модель вызова register?
Специально не указывал.


 
VMcL ©   (2004-04-14 17:47) [28]

>>REA ©  (14.04.04 17:45) [27]

В D по дефолту register.


 
Тимохов ©   (2004-04-14 17:50) [29]


> REA ©

Понял, т.е. вы хотите сделать published но только для классовых методов. И именно поэтому не хотите создавать объекты.

Предложение: сделайте таблицу пар соответствия

record
  ClassName: String;
  FriendClassName: String;
end;

занесите тутда

"TPanel", "Панель"
"TForm", "Форма"
и т.д.

потом берете List[i].classname, находите полученную строку в указанной выше таблице, выводите дружественное имя.

вполне нормальное решение.

уверен, что есть и другие (именно как вы хотите).

може же точно рабочее и простое.


 
Тимохов ©   (2004-04-14 17:51) [30]

дополение: тогда естествено придется делать регистрацию всех возможных классов.


 
REA ©   (2004-04-14 17:51) [31]

У меня функция, так что трюки с регистрами может и не пройдут.


 
REA ©   (2004-04-14 17:53) [32]

>Предложение: сделайте таблицу пар соответствия

Усложним задачу - компонеты лежат в динамически подгружаемых BPL.
Если не найду решения, я конечно все в базу затолкаю: имя класса, название, модуль и т.п.


 
default ©   (2004-04-14 17:54) [33]


TMyObj = class
 published
  class procedure PutHello(Param: Byte);
 end;

 TMyMeth = procedure (Param: Byte) of object;

var
 Form1: TForm1;
 M: TMyMeth;

implementation

{$R *.dfm}

class procedure TMyObj.PutHello(Param: Byte);
begin
Form1.Caption := ClassName + " " + IntToStr(Param)
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
TMethod(M).Code := TMyObj.MethodAddress("PutHello");
TMethod(M).Data := TMyObj;
M(20)
end;


вот так похорошему...


 
Юрий Зотов ©   (2004-04-14 21:04) [34]

> REA ©   (14.04.04 17:44) [26]

Сравните исходный вопрос и то, как Вы изложили его же в [26]. Просто, ясно, без всяких шибкоумных "интерфейсов". Есть разница, не правда ли?

Результат - [33]. Оказывается, все, что Вам, было нужно - это показать, как вызывается классовый метод через MethodAddress.

И если бы Вы сразу задали вопрос так, как в [26], то, вне всяких сомнений, тут же получили бы ответ. На чем проблема и была бы закрыта.

Неужели непонятно, что, формулируя вопрос, нужно думать не о том, как сделать его (и себя) "красивым", а о том, как изложить его максимально просто и понятно для всех?


 
REA ©   (2004-04-15 10:08) [35]

Во-первых возможных решений проблемы мне виделось 2 (в т.ч. с "шибкоумным" интерфейсом, который все-равно присутствует для других целей), а на самом деле их может быть и больше. Во-вторых [33] возможно корректен с точки зрения вызова, но не слишком корректен с точки зрения совместимости - решение использует не синтаксические конструкции языка, а информацию о типах, использованных в данной реализации.
Согласен - исходный вопрос был не слишком связен, но с учетом [2] уже достаточно понятен. Понимаю Ваше стремление к чистоте форума, но конструктивно пока получено решение от default, за что ему и спасибо. Сейчас попробую.


 
Тимохов ©   (2004-04-15 10:22) [36]


> REA ©   (15.04.04 10:08) [35]


> конструктивно пока получено решение от default, за что ему
> и спасибо

Давайте вы не будете решать, что конструктивно, а что нет.
Вам дано несколько рабочих решений.
Решайте, лучше, что подходит под ваш "шибкоумный" и непонятный исходный вопрос.


 
REA ©   (2004-04-15 10:29) [37]

Ok, спасибо всем.


 
Юрий Зотов ©   (2004-04-15 10:49) [38]

> REA ©   (15.04.04 10:08) [35]

1. Дело Ваше, можете не делать никаких выводов. Но тогда не удивляйтесь, если в дальнейшем ситуация повторится и в результате долгих коллективных мучений (Ваших, в том числе) Вы получите ответ через сутки, хотя могли бы получить его без проблем и за 5 минут.

2. С чем там несовместимо [33] и почему оно некорректно - кому как, а лично  мне это непонятно. А пробовать тут даже и нечего, это решение проверено уже тысячи раз и работает железно (да и чего бы ему не работать, когда оно сделано по полной "науке"). Осталось только оформить его в виде вот такой функции:
function GetFriendlyName(AClass: TClass): string;
в которую передается ЛЮБОЙ класс, а на выходе - либо Ваше FriendlyName, либо пустая строка (если метод не найден).



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

Текущий архив: 2004.05.02;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.025 c
1-1082109547
Andre____
2004-04-16 13:59
2004.05.02
Label с многоточием


14-1081635133
Soft
2004-04-11 02:12
2004.05.02
Соционика или типизация человеческой личности.


3-1081327000
YurikGl
2004-04-07 12:36
2004.05.02
DBExpres Открытие и закрытие соединения


1-1082130461
Zorlag
2004-04-16 19:47
2004.05.02
Плавное появление формы на экране


3-1080822047
Yad
2004-04-01 16:20
2004.05.02
Агрегатные поля