Expert Delphi
上QQ阅读APP看书,第一时间看更新

Helpers

Manipulating types in code can be even more readable when we define type helpers. Helpers extend a type vertically. You can define them on simple types, enumerations, records, or even on dynamic arrays. Delphi already comes with helpers defined for many built-in types, so they are easier to use in code. One good example is the very common task of converting an integer to a string, so it could be displayed as shown in the following code:

var s: string; i: integer; 
begin 
  i := 10; 
  s := IntToStr(i); // "old" style 
  s := i.ToString;  // more readable 
  s := 10.ToString; // that would work too 

Just right-click on the ToString method in this code and jump to the declaration. In the System.SysUtils unit, you will see helpers defined for many built-in types providing some additional useful methods, such as the minimum and maximum values for given built-in numerical types.

It is easy to define your own helper classes. Until Delphi 10, using helpers it was possible to access some private functionality of types that come out of the box with Delphi libraries, but since then this hack no longer works.

We already have the TSchoolGrade custom enumerated type. It would be useful to provide methods to convert a school grade value to a string or to a number. With helpers, it can be done in a really elegant way, as shown in the following code:

type 
  TSchoolGrade = (sgVeryGood, sgGood, sgSufficient, sgInsufficient); 
  TSchoolGrades = set of TSchoolGrade; 
 
const 
  QUALIFYING_GRADES: TSchoolGrades = [sgVeryGood, sgGood, sgSufficient]; 
 
type 
  TSchoolGradeHelper = record helper for TSchoolGrade 
  public 
    function ToString: string; 
    function ToInteger: integer; 
    function IsQualifying: boolean; 
  end; 
 
{ TSchoolGradeHelper } 
 
function TSchoolGradeHelper.IsQualifying: boolean; 
begin 
  Result := self in QUALIFYING_GRADES; 
end; 
 
function TSchoolGradeHelper.ToInteger: integer; 
begin 
  case self of 
    sgVeryGood: Result := 5; 
    sgGood: Result := 4; 
    sgSufficient: Result := 3; 
    sgInsufficient: Result := 2; 
  end; 
end; 
 
function TSchoolGradeHelper.ToString: string; 
begin 
  case self of 
    sgVeryGood: Result := 'Very Good'; 
    sgGood: Result := 'Good'; 
    sgSufficient: Result := 'Sufficient'; 
    sgInsufficient: Result := 'Insufficient'; 
  end; 
end; 

We use the self pseudo-variable in the implementation of a helper method to refer to the current value of the type we operate on.

Also, the function to check whether a given grade qualifies has been refactored as a helper method. It is more readable and improves the code structure.