这可能是一个简单的问题,但我想知道如何确保调用类的构造函数。
如果我有以下代码:
type TMyObject = class(TObject)
public
constructor Create;override;
end;
implementation
constructor TMyObject.Create;override;
begin
inherited;
//do other instantiation
end;
Delphi不允许这样做 - '无法覆盖静态方法'。
我想要做的是确保使用我的自定义Create构造函数创建对象并禁止调用祖先Create构造函数。
我目前解决这个问题的方法是定义一个唯一签名的Create构造函数,如下所示:
constructor Create(aName : String);overload;
但是程序员可能会调用祖先的Create()方法。
答案 0 :(得分:14)
您只需重新引入具有祖先名称的构造函数。一旦你这样做,用户就无法创建TMyObject
来调用TObject
中引入的构造函数。如果你使用这样的代码:
TMyObject = class
public
constructor Create;
end;
constructor TMyObject.Create;
begin
// I am not calling the inherited constructor because
// I do not want to.
end;
您不在override
上使用TMyObject.Create
修饰符,因为祖先的构造函数不是虚拟的。
使用此方案,用户无法使用祖先中引入的构造函数创建TMyObject
。在这种情况下,祖先是TObject
,它唯一的构造函数是TObject.Create
。如果用户编写此代码:
X := TMyObject.Create;
很明显,TMyObject
的构造函数将被调用,而不是TObject
中引入的构造函数。
如果您害怕用户为了使用祖先的构造函数创建您的类而跳过箍,您可以使用AfterConstruction
方法完成您的工作。这是一个虚方法,所以即使你的对象是使用祖先类型的类引用创建的,它也会被调用:
TMyObject = class
public
procedure AfterConstruction;override;
end;
答案 1 :(得分:6)
TObject.Create不是虚构造函数,因此是错误。
“其他程序员”可以调用祖先Create方法的唯一方法是故意跳过一些箍,例如。
var
ClassRef: TClass;
Obj : TObject;
begin
ClassRef := TMyObject;
Obj := ClassRef.Create;
end;
因为新引入的构造函数将隐藏非虚拟TObject.Create
你想要的更像是:
type TMyObject = class(TObject)
public
constructor Create;virtual;
end;
implementation
constructor TMyObject.Create;
begin
inherited;
//do other instantiation
end;