问题
Possible Duplicate:
How to cast a Interface to a Object in Delphi
Using Delphi 5; I have an interface that I cannot change for legacy reasons. I am passing (pointers to) that interface all over the place. The implementing class has several new properties - is there a way to force a cast from the interface to the actual implementation?
http://www.malcolmgroves.com/blog/?p=500 says that this is (newly) implemented in Delphi 2010, which strongly suggest that it wasn't possible before. Is this indeed the case, or is there a way I'm not familiar with? RTTI, maybe?
(I checked, and if pScore is TOleScore then
is indeed not allowed by the Delphi 5 compiler - here pScore
is my pScore: IScore
argument, and TOleScore
is the implementing class.)
回答1:
- The classic take on this is by Hallvard Vassbotn: Hack #7: Interface to Object
- More recently Barry Kelly, a Delphi compiler engineer, also provided an implementation: An ugly alternative to interface to object casting
I think both approaches should work.
Incidentally, does anyone know if Hallvard is still active? I've not come across him in the past few years.
回答2:
H/t to my boss, the answer is: use the incredibly useful JEDI library, specifically the GetImplementorOfInterface method.
回答3:
i do what the "possible duplicate" question's accepted answer does:
Have the object implement the IObject
interface:
IObject = interface(IUnknown)
['{39B4F98D-5CAC-42C5-AF8D-0237C8EFBE4C}']
function GetSelf: TObject;
end;
So it would be:
var
thingy: IThingy;
o: TOriginalThingy;
begin
o := (thingy as IObject).GetSelf as TOriginalThingy;
Update: To drive the point home, you can add a new interface to an existing object.
Existing object:
type
TOriginalThingy = class(TInterfacedObject, IThingy)
public
//IThingy
procedure DrinkCokeZero; safecall;
procedure ExcreteCokeZero; cafecall;
end;
Add IObject
as one of the interfaces it exposes:
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;
Typical usage:
procedure DiddleMyThingy(Thingy: IThingy);
var
o: TThingy;
begin
o := (Thingy as IObject).GetSelf as TThingy;
o.Diddle;
end;
来源:https://stackoverflow.com/questions/6414496/casting-a-delphi-interface-to-its-implementation-class-without-modifying-the-int