I'm having a problem with class operators in TDateTime.
type
TDateTime = class(TObject)
public
class operator Add(a: TDateTime; b: TTimeSpan): TDateTime;
class operator Subtract(a: TDateTime; b: TTimeSpan): TDateTime;
end;
implementation
class operator TDateTime.Add(a: TDateTime; b: TTimeSpan): TDateTime;
begin
result := TDateTime.Create(a.Ticks + b.Ticks);
end;
class operator TDateTime.Subtract(a: TDateTime; b: TTimeSpan): TDateTime;
begin
result := TDateTime.Create(a.Ticks - b.Ticks);
end;
The error occurred at 4th line
E2123 PROCEDURE, FUNCTION, PROPERTY, or VAR expected
I write this for Windows. But if it available only for .net and iOS, how can I do that for Windows?
It is possible to use operator overloading only for records, not for classes in Delphi for Windows.
http://docwiki.embarcadero.com/RADStudio/XE4/en/Operator_Overloading_(Delphi)
Some useful explanations
P.S. TDateTime is bad name for user type.
In desktop versions of Delphi (Windows, OSX), operator overloading is only available for records. For mobile versions of the compiler, ARC means that operator overloading is available for classes:
Operator Overloading for Classes
A very interesting side effect of using ARC memory management is that the compiler can handle the lifetime of temporary objects returned by functions. One specific case is that of temporary objects returned by operators. In fact, a brand new feature of the new Delphi compiler is the ability to define operators for classes, with the same syntax and model that has been available for records since Delphi 2006.
And if I recall correctly, operator overloading was available in the now discontinued .net compiler. This was again possible because the .net garbage collector could tidy up any temporary objects.
The doc excerpt above indicates why operator overloading is not possible with classes on non-ARC versions. Without some automatic lifetime management, temporary classes are leaked. On the other hand, temporary records can be created and destroyed in automatic storage on the stack.
That said, your somewhat mis-named type looks like it might be better as a value type in any case. So the solution to your problem is to:
- Give your type a better name, one that doesn't clash with a fundamental type.
- Change your type to be a
record
, that is a value type.
As a side note:
You can use it on classes in the Delphi .NET compiler (which since then has been discontinued) as the .NET garbage collection will eventually remove the new object instances returned by the operators, and more recently on the ARC based Delphi ARM compilers (that also release memory based on reference counting).
To answer your question:
You cannot use it on classes in the native Delphi compilers that do not support ARC (currently the Intel based x86 and x64 compilers for Windows, OS X and iOS simulator do not have ARC support), as it would heavily leak memory because the operators would return new object instances that nobody would free.
With the introduction of ARC (currently the ARM based mobile platforms), you can as those compiler compile this fine.
Notes:
- be careful redefining existing Delphi types like TDateTime
- be aware you can only use the below on ARC compilers so you are writing highly platform dependent code
- if you want to be cross platform, make it a value type like the TTimeStamp
record
is
In the code below (which only works for ARC), replace class
with record
do make it cross platform. It isn't by coincidence that the .NET framework has TimeSpan and DateTime (on which you might have based your code) are struct value types, not as class reference types.
To summarise, when writing cross platform code be aware of value and reference types and favour the record
value type when using operator overloading.
type
TTimeSpan = class
Ticks: Longint;
end;
TDateTime = class
public
Ticks: Longint;
class operator Add(a: TDateTime; b: TTimeSpan): TDateTime;
class operator Subtract(a: TDateTime; b: TTimeSpan): TDateTime;
constructor Create(aTicks: Longint);
end;
class operator TDateTime.Add(a: TDateTime; b: TTimeSpan): TDateTime;
begin
Result := TDateTime.Create(a.Ticks + b.Ticks);
end;
constructor TDateTime.Create(aTicks: Integer);
begin
Ticks := aTicks;
end;
class operator TDateTime.Subtract(a: TDateTime; b: TTimeSpan): TDateTime;
begin
Result := TDateTime.Create(a.Ticks - b.Ticks);
end;