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,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; 解决方法
当您打算在后代类中覆盖具有相同签名的方法的行为时,您必须在基类中将其声明为虚拟,然后后代类将使用override.
但是,如果您希望引入具有不同签名的新方法,那么如果要在同一个类中声明该方法,则必须使用重载指令.这简单地允许重复使用相同的方法名称,用于具有不同签名的有效,完全不同的方法.例如 : TCongruence = class(TObject) public constructor Create(a : integer); overload; constructor Create(a,n: integer); overload; end; 但是,如果要在后代类中声明一个新方法,则使用不同的签名,则不需要这些装饰. TCongruence = class(TObject) public constructor Create(a,n: integer); end; TCongruenceSystem = class(TCongruence) public constructor Create(a: array of TCongruence); end; 以上情况很好 – 您没有覆盖原始构造函数,只是引入了一个带有新签名的新构造函数.由于后者属于具有不同名称的新类,因此不存在歧义,并且不需要过载.您甚至可以通过以下方式访问祖先方法: TCongruence = class(TObject) private Fa,Fb,Fn : integer; public constructor Create(a,n: integer); end; TCongruenceSystem = class(TCongruence) private FArr : array of TCongruence; public constructor Create(a: array of TCongruence); end; constructor TCongruence.Create(a,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; 但是,如果没有过载指令,则不允许以下内容: var cs : TCongruenceSystem; begin cs := TCongruenceSystem.Create(1,2,3); end. 因为TCongruenceSystem隐藏了基类Create,它接受三个整数参数.但是,如果允许过载: TCongruence = class(TObject) private Fa,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,3);将被允许??并且祖先构造函数将用于构建后代类. 可以组合这些方法,例如: TCongruence = class(TObject) public constructor Create(a : integer); overload; virtual; {overridable} constructor Create(a,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的情况下,该函数不带参数,仅在返回类型上有所不同.但是,重载方法需要具有不同的参数集,因此在后代类中不允许这种类型的变异.如果您希望它也是具有不同返回类型的无参数函数,则后代类中的getSolutions将需要采用不同的名称. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |