Base class contructor is virtual.
The inherited class has override constructor.
Problem - without calling interited constructor in override it’s always called.
type
TBaseClass = public class
private
protected
public
constructor; virtual;
end;
TClass = public class(TBaseClass)
private
protected
public
constructor; override;
end;
implementation
constructor TBaseClass;
begin
System.Windows.MessageBox.Show('aaa');
end;
constructor TClass;
begin
System.Windows.MessageBox.Show('bbb');
end;
var vClass := new TClass(); - raises two MessageBox’es;
In .NET you are required to call the base class, so if you don’t, the compiler inserts an inherited call for you. Same goes for the JVM and Cocoa framework.
In base class I’ve got a property - Command - TCommand and an Execute method for executing this command. Command is created in constructor - it works.
In inherited class I’ve got also Command property - TTestCommad - reintroduce and TTestCommand is created in constructor.
When I create inherited class and call Execute - it raises TCommand - not TTestCommand.
If you can use a sub class for all types a generic can work:
IBaseCommand = public interface
end;
ISubCommand = public interface(IBaseCommand )end;
BaseModel<T> = public class where T: IBaseCommand;
public
property Command: T;
end;
SubModel = public class(BaseCommand<ISubCommand>) end;
Could you not simply decouple the initialisation of the Command reference from the constructor chain ? Make a virtual method for initialising the command object and call it when you need your first concrete reference to a command:
TBaseObject = class
private
fCommand: ICommand;
protected
function InitCommand: ICommand; virtual;
public
procedure Execute; virtual;
end;
procedure TBaseObject.InitCommand: ICommand;
begin
result := TBaseCommand.Create;
end;
procedure TBaseObject.Execute;
begin
if NOT Assigned(fCommand) then
fCommand := InitCommand;
...
end;
Then in your derived object class, override the InitCommand method to return an instance of the required command class:
TDerivedObject = class(TBaseObject)
private
fDerivedCommand: IDerivedCommand;
protected
function InitCommand: ICommand; override;
end;
function TDerivedObject.InitCommand: ICommand;
begin
fDerivedCommand := TDerivedCommand.Create;
result := fDerivedCommand;
end;
The TBaseObject class should not need to know about any new capabilities introduced by the IDerivedCommand interface - by definition the TBaseObject class knows only about IBaseCommand.
Similarly the IDerivedCommand interface should extend the IBaseCommand interface and TDerivedObject class needs only to retain an explictily typed reference to the IDerivedCommand interface if it makes use of those additional capabilities, otherwise it can continue to use the IBaseCommand reference (via a public or protected property on TBaseObject which provides that reference).