Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi record helper for double

Tags:

delphi

SITUATION

I have written a class for second degree equations that looks like this. You can find here the full code of the class but it's not very relevant for the question.

type
 TArrayOfDouble = array of array of double;

type
 TEqSecGrado = class
  private
   //variables
   a, b, c: double;
   delta: double;
   solutions: TArrayOfDouble;
   solRealCount: integer;
   solImaginaryCount: integer;
   class var currentIstances: integer;
   class var totalIstances: integer;
   //methods
   function getDelta(const vala, valb, valc: double): double; overload;
  public
   constructor Create(const a, b, c: double);
   destructor Destroy; override;
   //methods
   function getDelta: double; overload;
   function getSolutions: TArrayOfDouble; virtual;
   //properties
   property valueOfA: double read a;
   property valueOfB: double read b;
   property valueOfC: double read c;
   property realSolutionsCount: integer read solRealCount;
   property imaginarySolutionsCount: integer read solImaginaryCount;
   class property currentEquationsCount: integer read currentIstances;
   class property totalEquationsCount: integer read totalIstances;
 end;

I thought to create a new type called TArrayOfDouble that will contain the solution of my equation. In the main form I use the class in this way:

procedure TForm3.Button1Click(Sender: TObject);
var solver: TEqSecGrado;
    soluzioni: TArrayOfDouble;
begin

 //f(x) = 3x^2 - x - 2 -> [sol.1 = 1 | sol.2 = -0,666666666666667]
 solver := TEqSecGrado.Create(3,-1,-2);

 try
  soluzioni := solver.getSolutions; 
  //soluzioni[0][0] = 1; soluzioni[0][1] = 0; 
  //soluzioni[1][0] = -0,666666666666667; soluzioni[1][1] = 0; 
 finally
  solver.Free;
 end;

end;

Now I have the results inside soluzioni and I can output them. (I have used a matrix because in the first spot I put real solutions, in this case 1 and -0.67, and in the second sport immaginary solutions if needed).


QUESTION

When I output the solutions I want to convert them into a fraction. I wanted to do something like soluzioni[a][b].toFraction. So I thought I could use a record helper for double.

type
 TSupport = record helper for Double
   function toFraction: string;
   function toString: string; //I have added this LATER
 end;

Here I come with my doubt. Once I have created the TSupport and the toFraction method, I was able to call soluzioni[0][0].toFraction but I couldn't call soluzioni[i][0].toString.

To solve my problem I decided to add the function toString and everything worked. Does the record helper hide all the other methods? If I removed the record helper instead, I can use again the toString method as always.

I know that helpers are a way to extend a class without using inheritance, but why can I use only the methods I've declared in my helper?

like image 576
Alberto Miola Avatar asked Mar 12 '23 04:03

Alberto Miola


1 Answers

A limitation of class and record helpers is that only one can be active at once. The ToString method of Double is actually implemented in a record helper provided by the Delphi RTL. Once you attach your helper to the type, then the RTL helper is no longer active.

The documentation says:

You can define and associate multiple helpers with a single type. However, only zero or one helper applies in any specific location in source code. The helper defined in the nearest scope will apply. Class or record helper scope is determined in the normal Delphi fashion (for example, right to left in the unit's uses clause).

This is a long standing issue which Embarcadero has known about ever since helpers were introduced. In many long years they have not addressed the issue and with the best will in the world I think you should assume that they never will.

So, you have two choices:

  1. Attach your own helper, and accept that the functionality of the RTL helper will not be available to you.
  2. Implement your functionality by means other than a helper.
like image 121
David Heffernan Avatar answered Mar 20 '23 16:03

David Heffernan