Search code examples
delphilazarus

Why does a valid constructor in Delphi fail in Lazarus?


I'm working through tutorials in both Delphi and Lazarus. I'm using Delphi 10.1 Berlin Update 2 and Lazarus 1.6.2.

The following constructors work in Delphi, but the constructor in the TDog class fails in Lazarus with a "duplicate identifier" error.

All tutorials and forums I have searched look like this shouldn't be a problem.

unit Animal;

interface

uses
  classes;

type
  TAnimal = class
    private
      FName: String;
      FBrain: Integer;
      FBody: Integer;
      FSize: Integer;
      FWeight: Integer;
    public
      constructor create(Name: String; Brain, Body, Size, Weight: Integer);

      procedure Eat; virtual;

      property Name: String read FName;
      property Brain: Integer read FBrain;
      property Body: Integer read FBody;
      property Size: Integer read FSize;
      property Weight: Integer read FWeight;
  end;

implementation

constructor TAnimal.create(Name: String; Brain, Body, Size, Weight: Integer);
begin
  FName:= Name;
  FBrain:= Brain;
  FBody:= Body;
  FSize:= Size;
  FWeight:= Weight;
end;

procedure TAnimal.Eat;
begin
  Writeln('TAnimal.eat called');
end;

end.

unit Dog;

interface

uses
  classes,
  Animal;

type

TDog = class (TAnimal)
  private
    FEyes: Integer;
    FLegs: Integer;
    FTeeth: Integer;
    FTail: Integer;
    FCoat: String;

    procedure Chew;
  public
    constructor create(Name: String; Size, Weight, Eyes, Legs,
     Teeth, Tail: integer; Coat: String);

  procedure Eat; override;


end;

implementation

//following fails in Lazarus

constructor TDog.create(Name: String; Size, Weight, Eyes, Legs,
     Teeth, Tail: integer; Coat: String);

//this works, changing implementation also 
//constructor Create(aName: String; aSize, aWeight, Eyes, Legs,
//     Teeth, Tail: integer; Coat: String); 

begin
  inherited Create(Name, 1, 1, Size, Weight);
  FEyes:= Eyes;
  FLegs:= Legs;
  FTeeth:= Teeth;
  FTail:= Tail;
  FCoat:= Coat;
end;

procedure TDog.Chew;
begin
  Writeln('TDog.chew called');
end;

procedure TDog.Eat;
begin
  inherited;
  Writeln('TDog.eat called');
  chew;
end;

end.

Solution

  • From my experience with FreePascal/Lazarus you should not use same names for object method parameters and object properties, because it confuses the compiler as to know which one is which.

    So you should change your TDog.Constructor method into something like this:

    constructor create(AName: String; ASize, AWeight, AEyes, ALegs,
     ATeeth, ATail: integer; ACoat: String);
    

    Notice that I simply prefixed all your method parameters with A.

    In fact I recommend you use similar approach about naming method parameters everywhere because having same name for method parameters and object properties is also making code more confusing.

    While Delphi is capable of handling code which have method parameters with same names as object properties other compilers and Object Pascal dialects mostly don't.

    PS: When few years ago I tried to port some of my code from Delphi to FPC/Lazarus I ran into the exact same problem. I have spent whole day figuring out what the problem is not to mention two days refactoring my code with over 300 classes.

    And ever since then I'm trying to change my bad habit of still sometimes using same names for method parameters and properties.