Delphi子类构造函数覆盖

时间:2017-04-18 10:15:44

标签: delphi

我在一个文件中声明了以下类:

type
 TCongruence = class(TObject)
  private
   a, b, n, numClass: integer;
   solutions, vals: TSolutions;
   hasSolutions: boolean;
   function divides(a, b: integer): boolean;
   function modulo(a, b: integer): integer;
  public
   constructor Create(a, b, n: integer); virtual;
   function getSolutions: TSolutions; virtual;
   function gcdExtended(p, q: integer): TSolutions;
   class function getGCD(u, v: integer): integer;
   property valA: integer read a;
   property valB: integer read b;
   property valN: integer read n;
   property getClass: integer read numClass;
   property hasSol: boolean read hasSolutions;
 end;

type
 TConguenceSystem = class(TCongruence)
  private
   system: array of TCongruence;
  public
   constructor Create(a: array of TCongruence); override;
   function getSolutions: integer; override;
 end;

你可以看到的第二个是子类,因为我需要使用TCongruence类中实现的所有函数。我已经将构造函数声明为virtual,以便我可以在后代上调用override。

这是对的吗?我是否必须删除虚拟/覆盖并简单地使用这样的构造函数? (下同)

constructor Create(a: array of TCongruence); 

我想在这种情况下我隐藏了父亲的构造函数。我已经声明了这个构造函数:

constructor TConguenceSystem.Create(a: array of TCongruence);
var i: integer;
begin

 SetLength(system, length(a)); // private var system: array of TCongruence
 for i := Low(a) to High(a) do
  begin
   system[i] := a[i];
  end;

 solutions := false;

end;

1 个答案:

答案 0 :(得分:7)

当您打算在后代类中覆盖具有相同签名的方法的行为时,您必须在基类中声明它virtual,然后后代类将使用{{ 1}}。

但是,如果您希望引入一个带有不同签名的新方法,那么如果要在同一个类中声明该方法,则必须使用override指令 < / em>的。这简单地允许重复使用相同的方法名称,用于具有不同签名的有效,完全不同的方法。例如:

overload

但是,如果要在后代类中声明一个新方法,则使用不同的签名,则不需要这些装饰。

 TCongruence = class(TObject)
   public
     constructor Create(a : integer); overload;
     constructor Create(a, b, n: integer); overload;
 end;

以上情况很好 - 您没有覆盖原始构造函数,只是引入了一个带有新签名的新构造函数。由于后者属于具有不同名称的新类,因此不存在歧义,并且不需要 TCongruence = class(TObject) public constructor Create(a, b, n: integer); end; TCongruenceSystem = class(TCongruence) public constructor Create(a: array of TCongruence); end; 。您甚至可以通常的方式访问祖先方法:

overload

但是,如果没有 TCongruence = class(TObject) private Fa, Fb, Fn : integer; public constructor Create(a, b, n: integer); end; TCongruenceSystem = class(TCongruence) private FArr : array of TCongruence; public constructor Create(a: array of TCongruence); end; constructor TCongruence.Create(a, b, n: integer); begin inherited Create; Fa := a; Fb := b; Fn := n; end; constructor TCongruenceSystem.Create(a: array of TCongruence); var c : TCongruence; i : integer; begin inherited Create(a[0].Fa, a[1].Fb, a[2].Fn); SetLength(FArr, Length(a)); i := 0; for c in a do begin FArr[i] := c; Inc(i); end; end; 指令,则不允许以下内容:

overload

因为var cs : TCongruenceSystem; begin cs := TCongruenceSystem.Create(1, 2, 3); end. 隐藏了基类TCongruenceSystem,它需要三个Create个参数。但是,如果您允许integer

overload

然后允许上面调用 TCongruence = class(TObject) private Fa, Fb, Fn : integer; public constructor Create(a, b, n: integer); overload; end; TCongruenceSystem = class(TCongruence) private FArr : array of TCongruence; public constructor Create(a: array of TCongruence); overload; end; ,并使用祖先构造函数构建后代类。

这些方法可以合并,例如:

cs := TCongruenceSystem.Create(1, 2, 3);

对于构造函数,您将引入一个具有不同参数集的方法,因此允许这样做。但是,在 TCongruence = class(TObject) public constructor Create(a : integer); overload; virtual; {overridable} constructor Create(a, b, n: integer); overload; {only in base} end; TCongruenceSystem = class(TCongruence) public constructor Create(a:integer); overload; override; {overrides parent} constructor Create(a: string); overload; {introduce new} end; 的情况下,该函数不带参数,仅在返回类型上有所不同。但是,重载方法需要具有不同的参数集,因此在后代类中不允许这种类型的变异。如果您希望它也是一个具有不同返回类型的无参数函数,那么后代类中的getSolutions将需要使用不同的名称。