I am having trouble with the incorrect virtual Create() method being called during dynamic object creation. The parent method is called rather than the decendant method.
I have reviewed these posts, but can't figure it out:
Delphi - Create class from a string
Exploring TRTTIType and Descendants
Can I pass a Class type as a procedure parameter
and here Class_References
I have the following classes:
TCellObj = class(TPhysicsObj)
...
public
constructor Create(RgnMgr : TObject); virtual; //RgnMgr should be TRgnManager
destructor Destroy;
...
end;
TCellObjClass = Class of TCellObj;
--------------------------------
TCellTrialAObj = class(TCellObj)
...
public
...
constructor Create(RgnMgr : TObject); virtual; //RgnMgr should be TRgnManager
end;
--------------------------------
TRgnManager = class (TObject)
...
public
function NewCell(ClassRef : TCellObjClass) : TCellObj;
...
end;
....
function TRgnManager.NewCell(ClassRef : TCellObjClass) : TCellObj;
var CellObj : TCellObj;
begin
CellObj := ClassRef.Create(Self);
CellObj.DefaultInitialize;
CellObj.Color := TAlphaColors.Slategray;
FCellsList.Add(CellObj); //This will own objects.
SetSelection(CellObj);
Result := CellObj;
end;
And finally I start the process of dynamic object creation by the following line:
RgnManager.NewCell(TCellTrialAObj);
My goal is to have TRgnManager.NewCell to create any decendant of TCellObj based on the derived class passed in as a parameter. I will typecast the result to the appropriate class type during use.
When I step through the code with a debugger in NewCell, the Evaluate/Modify tool tells me that ClassRef = TCellTrialAObj as expected.
But when I step into the ClassRef.Create(self) line, it goes to TCellObj.Create(), NOT to TCellTrialAObj.Create() as I would have expected. This is the part I don't understand.
After the result has been assigned to CellObj, the Evaluate/Modify tool tells me that CellObj.ClassName = 'TCellTrialAObj';
So of ClassRef was of TCellTrialAObj, then why didn't the Create() function call TCellTrialAObj.Create() ??
Thanks in advance.
P.S. I am using Embarcadero® Delphi 10 Seattle Version 23.0.22248.5795
ADDENDUM
I cobbled together this function below, using examples from links above. It seems to work, and calls TCellTrialAObj.Create as desired. But I don't understand exactly how, why, or if I am actually doing it right. Can anyone explain?
function TRgnManager.NewCell(ClassRef : TCellObjClass) : TCellObj;
var CellObj : TCellObj;
RT : TRttiType;
C : TRttiContext;
T : TRttiInstanceType;
V : TValue;
begin
C := TRttiContext.Create;
T := (C.GetType(ClassRef) as TRttiInstanceType);
V := T.GetMethod('Create').Invoke(T.metaClassType,[self]);
C.Free;
CellObj := V.AsObject as TCellObj;
//CellObj := ClassRef.Create(Self);
CellObj.DefaultInitialize;
CellObj.Color := TAlphaColors.Slategray;
FCellsList.Add(CellObj); //This will own objects.
SetSelection(CellObj);
Result := CellObj;
end;