为什么 Delphi 中的有效构造函数在 Lazarus 中失败?

Why does a valid constructor in Delphi fail in Lazarus?

我正在学习 Delphi 和 Lazarus 中的教程。我正在使用 Delphi 10.1 Berlin Update 2 和 Lazarus 1.6.2。

以下构造函数在 Delphi 中工作,但 TDog class 中的构造函数在 Lazarus 中失败并出现 "duplicate identifier" 错误。

我搜索过的所有教程和论坛都是这样的,应该没有问题。

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.

根据我使用 FreePascal/Lazarus 的经验,您不应为对象方法参数和对象属性使用相同的名称,因为这会使编译器混淆,无法区分哪个是哪个。

所以你应该把你的 TDog.Constructor 方法改成这样:

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

请注意,我只是在您的所有方法参数前加上前缀 A

事实上,我建议您在任何地方都使用类似的方法命名方法参数,因为方法参数和对象属性具有相同的名称也会使代码更加混乱。

虽然 Delphi 能够处理方法参数与对象属性同名的代码,但其他编译器和 Object Pascal 方言大多不能。

PS:几年前我试图将我的一些代码从 Delphi 移植到 FPC/Lazarus 我 运行 遇到了完全相同的问题。我花了一整天的时间找出问题所在,更不用说用 300 多个 类 两天重构我的代码了。

从那时起,我一直在努力改变我有时仍然对方法参数和属性使用相同名称的坏习惯。