【问题标题】:Why does a valid constructor in Delphi fail in Lazarus?为什么 Delphi 中的有效构造函数在 Lazarus 中失败?
【发布时间】:2017-02-06 17:28:59
【问题描述】:

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

以下构造函数在 Delphi 中有效,但 TDog 类中的构造函数在 Lazarus 中失败并出现“重复标识符”错误。

我搜索过的所有教程和论坛看起来都应该没有问题。

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.

【问题讨论】:

  • 由于你是用不同的参数复制相同的构造函数名称,你需要reintroduce构造函数,否则使用{$mode delphi}
  • 感谢您的回复。我尝试了 {$mode delphi} 并且成功了。 reintroduce 没有任何效果,也不允许使用类名(Dog)作为实例变量。尽管在 Delphi 中一切正常,但从现在开始我将保持一切都是独一无二的。在 Java 和 C# 中,在类名之后以小写形式命名类实例变量似乎很常见,因为语言区分大小写。

标签: delphi lazarus


【解决方案1】:

根据我对 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 多个类重构我的代码了。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多