По работе захотел воспользоваться паттерном фабричный метод, и спрятать конструктор за protected декларацию.
program ProtectedConstructor;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TBaseClass = class
protected
FData : string;
constructor Create(const AData: string); virtual;
public
class function FactoryMethod(const Adata: string): TBaseClass;
property Data : string read FData;
end;
type
TInheritor = class (TBaseClass)
protected
constructor Create(const AData: string); override;
end;
constructor TBaseClass.Create(const AData: string);
begin
Fdata := Adata;
Writeln('TBaseClass.Create');
end;
class function TBaseClass.FactoryMethod(const Adata: string): TBaseClass;
begin
Result := TInheritor.Create(Adata)
end;
constructor TInheritor.Create(const AData: string);
begin
inherited;
Writeln('TInheritor.Create');
end;
var
MyClass : TBaseClass;
begin
try
MyClass := TBaseClass.FactoryMethod('Test');
try
Writeln(MyClass.Data);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
MyClass.Free;
Readln;
end;
end.
Ожидаемое поведение:
Я же решил разнести классы по разным модулям. TBaseClass в одном, и TInheritor в другом.
program BugProtectedConstructor;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
uBaseClass in 'uBaseClass.pas',
uInheritor in 'uInheritor.pas';
var
MyClass : TBaseClass;
begin
try
MyClass := TBaseClass.FactoryMethod('Test');
try
Writeln(MyClass.Data);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
finally
MyClass.Free;
Readln;
end;
end.
unit uBaseClass;
interface
type
TBaseClass = class
protected
FData : string;
constructor Create(const AData: string); virtual;
public
class function FactoryMethod(const Adata: string): TBaseClass;
property Data : string read FData;
end;
implementation
uses
uInheritor;
constructor TBaseClass.Create(const AData: string);
begin
Fdata := Adata;
Writeln('TBaseClass.Create');
end;
class function TBaseClass.FactoryMethod(const Adata: string): TBaseClass;
begin
Result := TInheritor.Create(Adata)
end;
end.
unit uInheritor;
interface
uses
uBaseClass;
type
TInheritor = class (TBaseClass)
protected
constructor Create(const AData: string); override;
end;
implementation
{ TInheritorOne }
constructor TInheritor.Create(const AData: string);
begin
inherited;
Writeln('TInheritor.create');
end;
end.
На выходе:
То есть в перегруженный конструктор мы не попадаем.
И вот вопрос, это баг или фича?
Запостил в quality portal
https://quality.embarcadero.com/browse/RSP-29333
