Приведение интерфейса delphi к его классу реализации без изменения интерфейса

Возможный дубликат:
Как преобразовать интерфейс в объект в Delphi

Использование Делфи 5; У меня есть интерфейс, который я не могу изменить по устаревшим причинам. Я передаю (указатели) этот интерфейс повсюду. Класс реализации имеет несколько новых свойств — есть ли способ принудительно привести интерфейс к фактической реализации?

http://www.malcolmgroves.com/blog/?p=500 говорит что это (недавно) реализовано в Delphi 2010, что убедительно свидетельствует о том, что раньше это было невозможно. Это действительно так или есть способ, с которым я не знаком? РТИ, может быть?

(Я проверил, и if pScore is TOleScore then действительно не разрешен компилятором Delphi 5 — здесь pScore — мой аргумент pScore: IScore, а TOleScore — класс реализации.)


person Marcel Popescu    schedule 20.06.2011    source источник
comment
Разница в том, что мне запрещено прикасаться к интерфейсу; этого ограничения не существовало в другом вопросе, AFAICT.   -  person Marcel Popescu    schedule 20.06.2011


Ответы (3)


Я думаю, что оба подхода должны работать.


Кстати, кто-нибудь знает, Холлвард все еще активен? Я не встречал его в последние несколько лет.

person David Heffernan    schedule 20.06.2011
comment
Да, Халлвард все еще активен, просто он больше не ведет блог. - person Marjan Venema; 20.06.2011
comment
Отмечено как ответ, потому что я не хочу отмечать свой :) - person Marcel Popescu; 20.06.2011
comment
@Марсель Спасибо! Из любопытства, чем версия JEDI отличается от версии Hallvard? - person David Heffernan; 20.06.2011

Привет моему боссу, ответ таков: используйте невероятно полезную библиотеку JEDI, в частности GetImplementorOfInterface метод.

person Marcel Popescu    schedule 20.06.2011

я делаю то, что делает принятый ответ на вопрос "возможный дубликат":

Пусть объект реализует интерфейс IObject:

IObject = interface(IUnknown)
    ['{39B4F98D-5CAC-42C5-AF8D-0237C8EFBE4C}']
    function GetSelf: TObject;
end;

Так было бы:

var
   thingy: IThingy;
   o: TOriginalThingy;

begin
   o := (thingy as IObject).GetSelf as TOriginalThingy;

Обновление. Чтобы довести до конца суть, вы можете добавить новый интерфейс к существующему объекту.

Существующий объект:

type
    TOriginalThingy = class(TInterfacedObject, IThingy)
    public
       //IThingy
       procedure DrinkCokeZero; safecall;
       procedure ExcreteCokeZero; cafecall;
    end;

Добавьте IObject в качестве одного из предоставляемых интерфейсов:

type
    TOriginalThingy = class(TInterfacedObject, IThingy, IObject)
    public
       //IThingy
       procedure DrinkCokeZero; safecall;
       procedure ExcreteCokeZero; cafecall;

       //IObject - provides a sneaky way to get the object implementing the interface
       function GetSelf: TObject;
    end;

    function TOriginalThingy.GetSelf: TObject;
    begin
       Result := Self;
    end;

Типичное использование:

    procedure DiddleMyThingy(Thingy: IThingy);
    var
       o: TThingy;
    begin
       o := (Thingy as IObject).GetSelf as TThingy;

       o.Diddle;
    end;
person Ian Boyd    schedule 20.06.2011
comment
Не похоже, что OP может изменить код, реализующий интерфейс. - person David Heffernan; 20.06.2011
comment
Да, к сожалению, я совершенно не могу потрогать интерфейс :( - person Marcel Popescu; 20.06.2011
comment
@Warren Нет, этот код работает на всех версиях Delphi. - person David Heffernan; 20.06.2011
comment
@ Дэвид, Марсель: я предполагаю, что ваш исходный интерфейс заблокирован (как и должно быть с интерфейсами). Используемый вами объект реализует другой совершенно отдельный интерфейс. С другой стороны, если, как прочитал Дэвид, вам не разрешено трогать какой-либо код - тогда это другая проблема. - person Ian Boyd; 21.06.2011
comment
Эй, смотрите, это версия Delphi, написанная, когда премьер-министром был Жан Кретьен. - person Ian Boyd; 21.06.2011
comment
Я тоже неправильно истолковал ваш ответ... да, это тоже сработает. (Я могу коснуться класса реализации, но не самого интерфейса.) К сожалению, я не могу отметить два вопроса как ответ :), так что просто +1 для вас. - person Marcel Popescu; 21.06.2011
comment
О, я вижу. Таким образом, мы используем возможность IUnknown, чтобы выбрать совершенно другой интерфейс, а не расширять заблокированный интерфейс. Очень хорошо. - person Warren P; 21.06.2011
comment
@Уоррен П: Точно! Объекты раскрывают себя миру через различные идентичности. Лучшим примером является TList, который представляет себя как IList, ICollection и IEnumerable. Это один и тот же объект TList, но вы представляете разное лицо разным людям для разных целей. - person Ian Boyd; 30.06.2011