I have a simple piece of code, that compiles in Delphi XE2 but not in XE3, and I don't know why. I have reduced the problematic code to a small bit and would like to know what's wrong with it in Delphi's opinion. Trying to compile a project containing this unit in Delphi XE 2 works fine, but in Delphi XE3 (trial), it gives "[dcc32 Error] AffineTransform.pas(26): E2382 Cannot call constructors using instance variables". The only "eccentric" thing I know of here is the use of the old-school "object" type, where the constructor isn't really exactly the same thing as in real objects (TObject-based class instances).
If I replace the words 'constructor' in this object with 'procedure', then it compiles ok, but why is this, and is this an ok change to do in my code, i.e. is it a change that will have no effect on the functionality?
unit AffineTransform;
interface
type
{ Rectangular area. }
TCoordRect = object
public
Left, Top, Right, Bottom: Real;
constructor CreatePos(ALeft, ATop, ARight, ABottom: Real);
procedure Include(AX, AY: Real);
end;
implementation
constructor TCoordRect.CreatePos(ALeft, ATop, ARight, ABottom: Real);
begin
Left := ALeft;
Top := ATop;
Right := ARight;
Bottom := ABottom;
end;
procedure TCoordRect.Include(AX, AY: Real);
begin
CreatePos(AX, AY, AX, AY)
end;
end.
For this legacy Turbo Pascal style object
, there is really no meaning to the keyword constructor
. Although an object
constructor does have some special treatment, there's absolutely no need for that here. What have here is nothing more than a record
with some methods.
The XE3 compiler was changed so that it no longer allows you to call a constructor on Self
inside an instance method. That is the case for both class
and object
. I've not seen any documentation of why this change was made. No doubt in time it will seep out.
Your immediate solution is to replace constructor
with procedure
. In the longer term, it would make sense to turn this into a record
rather than an object
.
I would also council you to change the name of the method to Initialize
. Some library designers seem to opt for using Create
and Free
methods on their records. This had led to immense amount of code being written like this:
ctx := TRttiContext.Create;
try
....
finally
ctx.Free;
end;
In fact all that code is spurious and can simply be removed! A TRttiContext
variable will automatically initialize itself.
That sort of design also sets a giant Heffalump Trap for that faction of Delphi coders that like to use FreeAndNil
. Passing a record to FreeAndNil
leads to some interesting fireworks!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With