Static class methods

1

Consider the following Delphi code:

unit Unit2;

interface

uses Dialogs;

type
  TNamedObj = class
  private
    FObjName: string;
  public
    constructor Create(const AName: string);
    procedure ShowName1;
    class procedure ShowName2(Obj: TNamedObj); static;
  end;

implementation

constructor TNamedObj.Create(const AName: string);
begin
  FObjName:= AName;
end;

procedure TNamedObj.ShowName1;
begin
  ShowMessage(FObjName);
end;

class procedure TNamedObj.ShowName2(Obj: TNamedObj);
begin
  ShowMessage(Obj.FObjName);
end;

end.

At a first glance ShowName2 looks like a useless addition. It does the same thing as ShowName1, and the compiler generates identical code for both.

Static class methods were made type compatible with ordinary procedures (functions). In the above example the static class method implementation of ShowName is type compatible with

type
  TShowProc = procedure(Obj: TNamedObj);

and that allows you to pass ShowName2 code as an argument:

type
  TShowProc = procedure(Obj: TNamedObj);

procedure TestShowName2(Proc: TShowProc);
var
  Obj: TNamedObj;

begin
  Obj:= TNamedObj.Create('Apple');
  Proc(Obj);
  Obj.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TestShowName2(TNamedObj.ShowName2);
end;

You need some unclean hackish trick to do the same with an object method:

type
  TShowMeth = procedure of object;

procedure TestShowName1(Proc: Pointer);
var
  Obj: TNamedObj;
  Meth: TMethod;

begin
  Obj:= TNamedObj.Create('Apple');
  Meth.Data:= Obj;
  Meth.Code:= Proc;
  TShowMeth(Meth);
  Obj.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  TestShowName1(@TNamedObj.ShowName1);
end;

See also the related SO question.

Record Constructors in Delphi

8

Record constructor in Delphi is a language feature that arises questions – what it is and when to use it instead of a record method. If you look at Delphi documentation you will find the following:

Records are constructed automatically, using a default no-argument constructor, but classes must be explicitly constructed. Because records have a default no-argument constructor, any user-defined record constructor must have one or more parameters.

The above documentation is nonsence. There is no such a thing as ‘a default no-argument constructor’ in Delphi. That arises one more question – why Delphi does not allow parameterless record constructors while allowing record constructors with parameters.

Record constructor in Delphi is a special syntax for a record method.

Suppose you are writing an advanced record that implements a complex number and need some initialization method. You may guess what is better, functional form:

type
  TComplex = record
    Re, Im: Double;
    function Create(ARe, AIm: Double): TComplex;
  end;

  function TComplex.Create(ARe, AIm: Double): TComplex;
  begin
    Result.Re:= ARe;
    Result.Im:= AIm;
  end;

or procedural form:

type
  TComplex = record
    Re, Im: Double;
    procedure Create(ARe, AIm: Double);
  end;

  procedure TComplex.Create(ARe, AIm: Double);
  begin
    Re:= ARe;
    Im:= AIm;
  end;

With the record constructor syntax you get both:

type
  TComplex = record
    Re, Im: Double;
    constructor Create(ARe, AIm: Double);
  end;

  constructor TComplex.Create(ARe, AIm: Double);
  begin
    Re:= ARe;
    Im:= AIm;
  end;

you can call record constructor as a function

var C: TComplex;

begin
  C:= TComplex.Create(0, 0);
end.

or as a procedure

var C: TComplex;

begin
  C.Create(0, 0);
end.

Both forms are correct.

The above example is oversimplified and may seem artificial, but sometimes an option to call a record method either as a function or as a procedure is useful and handy.