官术网_书友最值得收藏!

  • Expert Delphi
  • Pawe? G?owacki
  • 506字
  • 2021-07-02 20:44:24

Anonymous code

Anonymous code is all about treating code as data. You can assign an implementation of a function or procedure to a variable; you pass functions as parameters to other functions and receive them as results. This is a very powerful feature of the Object Pascal language. With anonymous code, the source code of your app can be more compact and maintainable.

A declaration of an anonymous method type has the following syntax:

type 
  TStringProc = reference to procedure (s: string); 

We are saying that TStringProc is a procedure that takes a string parameter. Now, we can define variables of this string type, assign implementation to them, pass them to functions, or, simply, just call them. Refer to the following code snippet:

procedure CallMe(const proc: TStringProc; msg: string); 
begin 
  proc(msg); 
end; 
 
procedure DoStringProc; 
var 
  proc: TStringProc; 
begin 
 
  proc := procedure(x: string) 
  begin 
    Log('Declared proc got: ' + x); 
  end; 
 
  CallMe(proc, 'Hello'); 
 
  CallMe( 
       procedure(v: string) 
       begin 
         Log('Inline code got: ' + v); 
       end, 
       'World'); 
end; 

Here, we have a CallMe procedure that takes as a parameter a chunk of code compatible with TStringProc and a string variable. There is also a proc local variable of the TStringProc type. In the first lines of the DoStringProc routine, we assign implementation to the proc variable. Note that there is no identifier after the procedure keyword. The parameter declaration follows immediately. This is why it is called anonymous code. It does not need a name because it is never referenced by name. In the first call to CallMe, we pass the proc variable as a parameter. The second call to CallMe is even more compact; we define the implementation of an anonymous procedure, in-place.

A more useful example of using anonymous code could be the sorting of a generic list. We can define the TPersonList class and implement the SortByFullName method:

unit uPersonList; 
 
interface 
 
uses 
  System.Generics.Collections, // TObjectList<T> 
  uPerson;  // TPerson 
 
type 
  TPersonList = class(TObjectList<TPerson>) 
    procedure SortByFullName; 
  end; 
 
implementation 
 
uses 
  System.Generics.Defaults, // IComparer, TComparison 
  System.SysUtils; // CompareStr 
 
 
{ TPersonList } 
 
procedure TPersonList.SortByFullName; 
var 
  Comparer : IComparer<TPerson>; 
  Comparison : TComparison<TPerson>; 
begin 
  Comparison := function(const p1, p2: TPerson): integer 
  begin 
     Result := CompareStr(p1.FullName, p2.FullName); 
  end; 
  Comparer := TComparer<TPerson>.Construct(Comparison); 
  inherited Sort(Comparer); 
end; 
 
end. 

The generic object list class defines the Sort method, which can be overridden in the descendent classes. As its parameter, it expects a generic comparer class, which is only responsible for comparing any two elements of the underlying class; it returns an integer value that needs to be negative if the first element is less than the second, "zero" if they are the same, or a positive value if the first element is greater than the second one. Here, we construct the TComparer class, which is responsible for comparting to TPerson objects. Luckily in the System.SysUtils unit, there is a very handy CompareStr function that we can use directly. Our comparer is referenced by its implementing interface, and that's why we do not need to free it afterwards. It will be freed automatically by the interface reference counting mechanism.

主站蜘蛛池模板: 普安县| 云霄县| 镇沅| 枝江市| 保德县| 湄潭县| 招远市| 龙陵县| 鱼台县| 崇左市| 天水市| 肇源县| 泗阳县| 余姚市| 临高县| 连州市| 柘城县| 荣成市| 巴塘县| 灵川县| 甘孜县| 永川市| 凉山| 清水河县| 祁阳县| 浦东新区| 壶关县| 潼关县| 若羌县| 永嘉县| 临沧市| 随州市| 灵丘县| 永胜县| 凌源市| 中方县| 新营市| 瑞昌市| 庄浪县| 黑河市| 屏山县|