Перечислите все классы Delphi, которые реализуют данный интерфейс?

С новым расширенным RTTI в Delphi 2010, может, приложение Delphi (во время выполнения) создает список всех классов, которые реализуют данный интерфейс?

8
задан mjn 3 September 2010 в 16:32
поделиться

1 ответ

Я чувствую, что Apache Portable Runtime может помочь с тем, что вы ищете. Apache HTTPD использовал эту библиотеку для абстрагирования специфичного для платформы кода, так что серверный код фокусируется на логике и вызывает методы в APR, и они преобразуются в базовые функции операционной системы.

Конечно, в нем может быть больше инструментов, чем вам строго нужно...

-121--4690779-

Ответ касается корней С объекта-C. Objective-C изначально был написан как предпроцессор компилятора для C. То есть Objective-C не был скомпилирован настолько, насколько он был преобразован в прямой C, а затем скомпилирован.

Начните с определения типа id . Объявляется как:

typedef struct objc_object {
    Class isa;
} *id;

То есть id является указателем на структуру, первое поле которой имеет тип Class (который сам по себе является указателем на структуру, определяющую класс). Теперь рассмотрим NSObject :

@interface NSObject <NSObject> {
    Class   isa;
}

Обратите внимание, что макет NSObject и макет типа, на который указывает id , идентичны. Это потому, что в действительности экземпляр объекта Objective-C действительно является просто указателем на структуру, первое поле которой - всегда указатель - указывает на класс, который содержит методы для этого экземпляра (наряду с некоторыми другими метаданными).

Когда вы подкласс NSObject и добавляете некоторые переменные экземпляра, вы просто создаете новую структуру C, которая содержит переменные экземпляра в качестве слотов в этой структуре, конкатенированных на слотах для переменных экземпляра для всех суперклассов. (Современная среда выполнения работает несколько иначе, так что суперкласс может иметь добавленные ivars, не требуя перекомпиляции всех подклассов).

Рассмотрим разницу между этими двумя переменными:

NSRect foo;
NSRect *bar;

(NSRect быть простая структура C - не участвует в ObjC). foo создается с местом хранения в стеке. Он не выживет, когда кадр стека будет закрыт, но вам также не придется освобождать память. bar - ссылка на структуру NSRect, которая, скорее всего, была создана в куче с помощью malloc () .

Если вы попытаетесь сказать:

NSArray foo;
NSArray *bar;

Компилятор пожалуется на первый, сказав, что что-то по линии стековых объектов не допускается в Objective-C . Другими словами, все объекты Objective-C должны быть выделены из кучи (более или менее - есть одно или два исключения, но они сравнительно эзотерические для этого обсуждения), и в результате вы всегда ссылаетесь на объект через адрес указанного объекта в кучи; вы всегда работаете с указателями на объекты (и тип id действительно является просто указателем на любой старый объект).

Возвращаясь к корням препроцессора языка C, можно перевести каждый вызов метода в эквивалентную строку C. Например, следующие две строки кода идентичны:

[myArray objectAtIndex: 42];
objc_msgSend(myArray, @selector(objectAtIndex:), 42);

Аналогично,метод, объявленный так:

- (id) objectAtIndex: (NSUInteger) a;

Эквивалентен функции C, объявленной так:

id object_at_index(id self, SEL _cmd, NSUInteger a);

И, глядя на objc _ msgSend () , первый аргумент объявляется как имеющий тип id :

OBJC_EXPORT id objc_msgSend(id self, SEL op, ...);

И именно поэтому вы не используете * foo в качестве цели вызова метода. Выполните трансляцию с помощью описанных выше форм - вызов [myArray objectAtIndex: 42] преобразуется в приведенный выше вызов функции C, который затем должен вызвать что-либо с объявлением эквивалентного вызова функции C (все они одеты в синтаксис метода).

Ссылка на объект передается, потому что она дает мессенджеру - objc_msgSend () доступ к классу, чтобы затем найти реализацию метода - а также эту ссылку, которая затем становится первым параметром - я - метода, который в конечном итоге выполняется.

Если вы действительно хотите углубиться, начните здесь . Но не беспокойтесь, пока вы полностью не заработали это .

-121--1080959-

Технически да, если интерфейс имеет GUID и классы, о которых вы заботитесь, находятся в интерфейсных секциях блоков.

Блок RTTI еще не имеет API для описания всех интерфейсов, реализуемых классом, но данные находятся в информации о типе.

GUID для типа интерфейса может быть получен из этого выражения:

GetTypeData(TypeInfo(ITheInterface))^.Guid

или:

ctx: TRttiContext;
// ...
(ctx.GetType(TypeInfo(ITheInterface)) as TRttiInterfaceType).GUID

Класс типа экземпляра может быть затем проверен с помощью TClass.GetInteriveEntry (IID) - если он возвращает non-nil, класс реализует интерфейс.

Все классы, объявленные в интерфейсных секциях единиц, можно получить с помощью TRttiContext.GetTypes .

Запись фактической итерации и кода извлечения остается упражнением для читателя.

20
ответ дан 5 December 2019 в 08:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: