使用reintroduce隐藏无参数的Create方法?

6

我开始学习 Delphi 时读到,避免无用的调用不带参数的 Create 构造函数的唯一方法是在其中抛出异常或断言。 本周我第一次使用 reintroduce 关键字时,发现它似乎也解决了这个问题。

Test = class
private
    n_ : Integer;
public
    constructor Create(n : Integer); reintroduce;
end;

调用Test.Create会给我想要的编译器错误。这种方法有什么问题吗?

2个回答

4

问题很简单:如果你重新引入一个方法,它将隐藏父类的方法。这正是你想要的,但请检查以下代码:

type
  TClassParent = class
  public
    procedure DoSomething; overload;
    procedure DoSomething(Something: Integer); overload;
  end;
  TClassChild = class(TClassParent)
  public
    procedure DoSomething(SomethingElse: string); reintroduce;
  end;
var
  Child: TClassChild;
begin
  Child := TClassChild.Create;
  Child.DoSomething;
  Child.DoSomething(1024);
  Child.DoSomething('Something');

这会给你带来两个错误!为什么呢?因为父类中的两个DoSomething方法现在被隐藏了!有时,你希望这样做。有时候又不希望。当你不希望的时候,你需要将这些缺失的方法再次添加到子类中,并像以下这样调用继承方法:
procedure TClassChild.DoSomething(SomethingElse: string);
begin
  inherited DoSomething(SomethingElse);
end;

再次提醒,这正是您想要的,对吧?隐藏所有具有相同名称的父方法。但请不要忘记,您仍然可以调用继承的方法。
当将接口链接到父类时,请注意子类仍将支持该接口,但通过接口而不是对象调用方法将导致调用父类而不是子类!
重新引入方法是一种很好的做法,以便隐藏来自父类的方法。但是,它也会隐藏具有相同名称的虚拟方法!通常,最好只覆盖虚拟方法,但是当更改参数列表时,使用 reintroduce 实际上会在正常情况下禁用从类外部访问父类。但是在类内部,您仍然可以访问它们,而没有警告...

谢谢!隐藏基类的所有构造函数正是我想要的。在大多数情况下,调用基类构造函数是不足以完全初始化具体对象的。 - hansmaad
请注意,reintroduce 仅仅是抑制编译器警告。运行时的行为与是否使用它相同。如果你隐藏了一个析构函数,请小心。如果你调用 TObject.Free,子类的析构函数将永远不会被调用。 - Kenneth Cochran
@Codeelegance,不需要Reintroduce!重新引入会使父类方法不可用!没有重新引入,您仍然可以调用父类方法而不会出现任何问题。使用重新引入,这些父类方法将“消失”,只能从子类中访问。 - Wim ten Brink

1

如果您使用另一种签名定义构造函数,则会有效地隐藏其他构造函数,因此会出现警告。指令 reintroduce 告诉编译器您知道自己在做什么,因此不会显示警告。

因此,唯一的影响是隐藏先前的构造函数。

如果您想要多个构造函数变体,则可以使用 overload 指令。


编译器何时开始警告隐藏非虚拟方法的问题?肯定是在 Delphi 2005 之后的某个时间。我从未见过这样的警告。 - Rob Kennedy
不完全地覆盖,通过在子类中定义任何方法仍将公开父类方法给您的代码。重新引入将隐藏父类方法,确保您无法直接使用它。(虽然仍可以通过调用其为继承方法或通过接口来使用它。) - Wim ten Brink

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接