【问题标题】:Generate compiler error if property is not set如果未设置属性,则生成编译器错误
【发布时间】:2016-09-13 14:59:26
【问题描述】:

如果我的对象中的某个属性未设置,我希望能够创建编译器错误/警告。假设我有以下课程:

interface

type
  TBarkevent = procedure (Bark : String) of object;

  TDog = class
  private
    FOnBark : TBarkevent;
    procedure SetBark(const Value: TBarkevent);
    function GetBark: TBarkEvent;
  public
    procedure Bark;
    property OnBark : TBarkEvent read GetBark write SetBark;
    constructor Create;
  end;

implementation

{ TDog }

procedure TDog.Bark;
begin
  if Assigned(OnBark) then
    OnBark('Woof!')
end;

constructor TDog.Create;
begin
end;

function TDog.GetBark: TBarkEvent;
begin
  Result := FOnBark;
end;

procedure TDog.SetBark(const Value: TBarkevent);
begin
  FOnBark := Value;
end;

我在另一个单元中使用TDog 类,如下所示:

var
  Dog : TDog;
begin
  Dog := TDog.Create;
  Dog.OnBark := DogBark;
  Dog.Bark;

现在,一旦调用了Bark() 过程,就会触发OnBark 事件。

我的问题:

我是否可以强制指定OnBark 属性,以便在未设置事件时发出编译器错误/警告?

【问题讨论】:

  • 有时你必须站出来把事情做好。编译器无法为您完成工作。
  • @DavidHeffernan 问题是,从现在起几年后,除我之外的其他人最终可能会使用此代码,并且有一些东西可以告诉他们他们早期犯了错误,这可以节省大量时间和精力跨度>
  • 那叫文档
  • 确实,Dog.ScratchEar; 不会为你带来任何魔法 :-)

标签: delphi firemonkey delphi-10-seattle


【解决方案1】:

将你的类定义为:

TDog = class
private
  FOnBark : TBarkevent;
  procedure SetBark(const Value: TBarkevent);
  function GetBark: TBarkEvent;
public
  procedure Bark;
  property OnBark : TBarkEvent read GetBark write SetBark;
  constructor Create(Bark : TBarkEvent);
end;

这样,您不能在不指定事件的情况下实例化TDog 对象。如果你尝试,你会得到一个编译器错误。

【讨论】:

  • 是的,但是仍然可以为事件分配 nil 值,这不满足 OP 的要求。
  • 同意@RemyLebeau,但可以在构造函数中检查 nil 并在这种情况下引发异常
  • @RemyLebeau:为什么不呢?分配 NIL 值仍然是分配值。在 Bark 方法中甚至可以检查该值是否为非 NIL,因此(对我而言)很明显 NIL 值是有效值。如果没有,Bark 方法应该只调用 FOnBark 事件,如果没有为其分配非 NIL 值,则让它崩溃。如果 NIL 不是有效值,则应执行 CONSTRUCTOR 中的检查,并删除 Bark 方法中的检查。
【解决方案2】:

首先:否。不可能在编译时检查这样的属性。

几乎强制实现OnBark 事件,您可以将其添加为构造函数参数,而不是将其发布为读/写属性.然后,您可以使用Assert() 在运行时检查它,在调用构造函数时是否已将有效的回调方法传递给构造函数。

要使其真正强制,您可以声明以下内容:

TCustomDog = class
public
  procedure Bark; virtual; abstract;
end;

因此,每个使用TCustomDog 类的人都必须实现Bark 过程。如果他不这样做,则会发出编译器警告。

【讨论】:

  • 澄清一下:CONSTRUCTOR 方式会产生错误。 ABSTRACT 方式(默认情况下)只会生成警告......因此(IMO)CONSTRUCTOR 方式将是更好的选择。
  • @kobik:它没有。代码必须从 TCustomDog 派生另一个类,并使用具体实现而不是使用事件覆盖 Bark()
  • @HeartWare 没错。我自己也会选择构造方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
相关资源
最近更新 更多