Как выглядит class (схема)
Модератор: Модераторы
-
MandelLamoureux
- незнакомец
- Сообщения: 3
- Зарегистрирован: 29.03.2015 18:32:12
Как выглядит class (схема)
Всем привет. Мне было очень интересно узнать как устроены классы, и однажды вечером я решил нарисовать схему.
На схеме изображено как далеко можно зайти следуя по ссылкам в только что созданном экземпляре класса (class, а не object), какой и сколько RTTI информации существует о классе его методах и свойствах.
Это всего лишь моё небольшое исследование, которое я провёл исключительно из интереса.
Для примера я взял класс с довольно простой иерархией, TUnicorn <- TPony <- TObject
Код можно посмотреть здесь, его совсем немного: http://pastebin.com/rTKkuT0U
Перед тем как показать схему:
1) Адреса заменил на константы вида $(YYY_ADDR_ZZ), в принципе на них обращать внимания не стоит, все указатели отметил стрелками (там где адреса должны совпадать, они совпадают).
2) Если структура пуста, она изображена без полей, для экономии места, например: TInterfaceTable пуста, т.к. в классах не реализован ни один интерфейс.
3) Во всей этой схеме есть 1 поле - назначение которого для меня загадка, ClassTable (отмечен фиолетовым) если Вы про него что-то знаете, дайте мне знать.
4) Структура TPropList сама по себе не существует, её в рантайме создал я, для получения списка свойств (но информация о самих свойствах, на которую есть указатели в этой таблице - существует всегда).
Собственно сама схема, трижды всё перепроверил, но ошибки не исключены: https://www.dropbox.com/sh/luewmnj8fi0d ... NtjZa?dl=0
Если обнаружили ошибки или неточности, дайте мне знать!
upd0: вернул картинку.
На схеме изображено как далеко можно зайти следуя по ссылкам в только что созданном экземпляре класса (class, а не object), какой и сколько RTTI информации существует о классе его методах и свойствах.
Это всего лишь моё небольшое исследование, которое я провёл исключительно из интереса.
Для примера я взял класс с довольно простой иерархией, TUnicorn <- TPony <- TObject
Код можно посмотреть здесь, его совсем немного: http://pastebin.com/rTKkuT0U
Перед тем как показать схему:
1) Адреса заменил на константы вида $(YYY_ADDR_ZZ), в принципе на них обращать внимания не стоит, все указатели отметил стрелками (там где адреса должны совпадать, они совпадают).
2) Если структура пуста, она изображена без полей, для экономии места, например: TInterfaceTable пуста, т.к. в классах не реализован ни один интерфейс.
3) Во всей этой схеме есть 1 поле - назначение которого для меня загадка, ClassTable (отмечен фиолетовым) если Вы про него что-то знаете, дайте мне знать.
4) Структура TPropList сама по себе не существует, её в рантайме создал я, для получения списка свойств (но информация о самих свойствах, на которую есть указатели в этой таблице - существует всегда).
Собственно сама схема, трижды всё перепроверил, но ошибки не исключены: https://www.dropbox.com/sh/luewmnj8fi0d ... NtjZa?dl=0
Если обнаружили ошибки или неточности, дайте мне знать!
upd0: вернул картинку.
Последний раз редактировалось MandelLamoureux 27.05.2017 21:19:18, всего редактировалось 1 раз.
Жалко картинка не сохранилась 
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
неточность в названиях классов.. получается, что единорог это всегда маленькая лошадь?
Собственно, название говорит за себя...
Скорее всего, это таблица (порожденных и/или порождаемых) классов. Или ссылка на элемент в оной. Но подробнее можно было бы узнать если увидеть картинку.
Добавлено спустя 12 минут 26 секунд:
Если порыться в исходниках, то этот метод определен так
Если я правильно понимаю, то это указатель на структуру класса.
MandelLamoureux писал(а):ClassTable
Собственно, название говорит за себя...
Скорее всего, это таблица (порожденных и/или порождаемых) классов. Или ссылка на элемент в оной. Но подробнее можно было бы узнать если увидеть картинку.
Добавлено спустя 12 минут 26 секунд:
Если порыться в исходниках, то этот метод определен так
Код: Выделить всё
class function TObject.ClassType : TClass;
begin
ClassType:=TClass(Pointer(Self))
end; Если я правильно понимаю, то это указатель на структуру класса.
Да, Вы правильно понимаете.
На самом деле все можно узнать либо аналитически, либо почитав тематические блоги и т.п. Но на это потребуются усилия и серьезные исследования. Вот эта картинка мне показалась отражающей все необходимые аспекты для быстрого ознакомления, а где я её сохранил - найти теперь не могу.
Зачем это нужно? Ну, в новых Дельфях не особо и нужно - там есть готовые решения, а в реальном мире:
* добавить данные в VMT класса (опять же RunTime), чтобы все объекты этого класса (но не их наследники) имели доступ к этим данным (вполне возможно сделать, используя какие-либо неиспользуемые части VMT, к примеру AutoTable)
* добавить хук на изменения свойства в RunTime (всё просто, пока не столкнетесь с переопределением статического метода, который не удается найти в структуре класса)
Возможно я что-то не знаю и есть уже решения для FPC/OldDelphi (в JEDI есть, но их приходится дописывать и обновлять, потому что все как надо не работает или нет возможности работать с DynArray через RTTI)
На самом деле все можно узнать либо аналитически, либо почитав тематические блоги и т.п. Но на это потребуются усилия и серьезные исследования. Вот эта картинка мне показалась отражающей все необходимые аспекты для быстрого ознакомления, а где я её сохранил - найти теперь не могу.
Зачем это нужно? Ну, в новых Дельфях не особо и нужно - там есть готовые решения, а в реальном мире:
* добавить данные в VMT класса (опять же RunTime), чтобы все объекты этого класса (но не их наследники) имели доступ к этим данным (вполне возможно сделать, используя какие-либо неиспользуемые части VMT, к примеру AutoTable)
* добавить хук на изменения свойства в RunTime (всё просто, пока не столкнетесь с переопределением статического метода, который не удается найти в структуре класса)
Возможно я что-то не знаю и есть уже решения для FPC/OldDelphi (в JEDI есть, но их приходится дописывать и обновлять, потому что все как надо не работает или нет возможности работать с DynArray через RTTI)
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
wavebvg писал(а):потому что все как надо не работает или нет возможности работать с DynArray через RTTI)
Я бы не назвал это недостатком.
wavebvg писал(а):всё просто, пока не столкнетесь с переопределением статического метода, который не удается найти в структуре класса
А смысл? Если это требуется то, в большинстве случаев, что-то сделано не так. Использование подобных хаков может легко поломать программу.
wavebvg писал(а): или нет возможности работать с DynArray через RTTI
Вполне логично... это ведь внутренняя кухня , к которой доступ как бы должен отсутствовать.
Лекс Айрин писал(а):А смысл? Если это требуется то, в большинстве случаев, что-то сделано не так. Использование подобных хаков может легко поломать программу.
К примеру, чтобы отделить реализацию от структуры.
1. Берем обычный блоатваре датасет
2. Берем объект (к примеру Item коллекции, да и саму коллекцию тоже)
3. Пишем код-эмуляцию аннотации - сопоставления полей
4. Загрузка/сохранение коллекции становится куда проще, появляется возможность загружать составные структуры и т.п. без необходимости рулить DataSet-ом с его FieldByName на каждый **** или созданием статических полей и привязки логики к внутренностям DM
Лекс Айрин писал(а):Вполне логично... это ведь внутренняя кухня , к которой доступ как бы должен отсутствовать.
С такой логикой весь RTTI - внутренняя логика и не стоит им пользоваться
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
wavebvg писал(а):4. Загрузка/сохранение коллекции становится куда проще, появляется возможность загружать составные структуры и т.п. без необходимости рулить DataSet-ом с его FieldByName на каждый **** или созданием статических полей и привязки логики к внутренностям DM
Я бы использовал либо ссылку на сырые (или не очень) данные, либо дженерики.
wavebvg писал(а):С такой логикой весь RTTI - внутренняя логика и не стоит им пользоваться
Конечно. Но это не вина создателей библиотеки, так что приходится пользоваться.
- serbod
- постоялец
- Сообщения: 449
- Зарегистрирован: 16.09.2016 10:03:02
- Откуда: Минск
- Контактная информация:
MandelLamoureux писал(а):Если обнаружили ошибки или неточности, дайте мне знать!
Twilight Sparkle уже давно не TUnicorn, а TPonyPrincess(TPony, IUnicorn, IPegasus). И вообще, тема интерфейсов не раскрыта.
wavebvg писал(а):Берем обычный блоатваре датасет, пишем код-эмуляцию аннотации - сопоставления полей
TDataSet это базовый класс с произвольным набором полей, изменяемых в runtime. Он может быть виртуальным, то есть не содержать данные, а служить оберткой для доступа к данным. А для вашего случая существуют published property, которые автоматом попадают в RTTI и доступны как в IDE, так и по именам в runtime.
Во внутреннюю структуру объектов действительно лучше не лезть, она может отличаться на разных платформах, архитектурах и версиях компилятора. Наружу торчит вполне достаточно protected и public свойств. Еще часть возможностей доступно через функции и глобальные переменные модуля System.
-
MandelLamoureux
- незнакомец
- Сообщения: 3
- Зарегистрирован: 29.03.2015 18:32:12
Первый ответ в теме чуть более чем через 2 года. 
А картинку я вернул.
А картинку я вернул.
>>3) Во всей этой схеме есть 1 поле - назначение которого для меня загадка, ClassTable (отмечен фиолетовым) если Вы про него что-то знаете, дайте мне знать.
Подобные вещи я ковырял когдато очень давно, поэтому - емнип это таблица типов публишед полей, тип поля берется из нее по смещению ClassTypeIndex из своего описания.
Подобные вещи я ковырял когдато очень давно, поэтому - емнип это таблица типов публишед полей, тип поля берется из нее по смещению ClassTypeIndex из своего описания.
Последний раз редактировалось zub 28.05.2017 01:51:53, всего редактировалось 1 раз.
-
MandelLamoureux
- незнакомец
- Сообщения: 3
- Зарегистрирован: 29.03.2015 18:32:12
Спасибо, не догадался проверить это раньше, в данный момент времени нет, не знаю есть ли смысл переделывать схему. 
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
MandelLamoureux, конечно. Для лучшего понимания процесса использования классов.
С содержимым картинки при обычном "процессе использования" никогда не столкнешся. ИМХО гораздо полезней чем глядеть на такие картинки - смотреть в исходники
- Лекс Айрин
- долгожитель
- Сообщения: 5723
- Зарегистрирован: 19.02.2013 16:54:51
- Откуда: Волгоград
- Контактная информация:
zub, ну это по любому. Благо, они доступны всегда
