Bottom line: How can we hide the constructor of a class?  As far as I
can see you cannot decrease the visibility of a method compared to
it's inherited class. Why shouldn't we be allowed to?  C++, C# does!

I found this by trying to implement a True Singleton in Free Pascal /
Delphi.  For those that don't know, a Singleton is a Design Pattern
that allows only one instance of a class.  It seems it is impossible
to do in Free Pascal / Delphi.  :-(

See attached code for a demonstration of the problem.

And here is the output.  The first two '>> PrintData' sections are
correct and use the singleton as it should be used.  The third '>>
PrintData' section is by declaring a new variable of TSingleton and
creating it.

The problem is even though the constructor is declared in the
protected section, Free Pascal just gives a compiler warning and it
stays public.  What is the reason why we may not decrease visibility
of methods or properties?  Couldn't we add this feature to Free
Pascal? Or at least in the ObjFPC mode!

Is there another way of implementing a true singleton in Free Pascal,
maybe using some other language construct.


-----------------------  START Output  ---------------
[graemeg-linux] singleton > ./singtest
PrintData
hello world
---------
PrintData
hello world
hello world 2
---------
PrintData

-----------------------  END Output  ---------------

--
Graeme Geldenhuys

There's no place like S34° 03.168'  E018° 49.342'
unit sing; //first singleton

{$mode objfpc}{$H+}

interface

type

TSingleton = class
private
  fData : string;
protected
  constructor Create;
public
  procedure PrintData; virtual;
end;

function GetSingleton : TSingleton;

implementation

var
  asing : TSingleton = nil;

function GetSingleton : TSingleton;
begin
  if asing = nil then
    asing := TSingleton.Create;
   Result := asing;
end;

constructor TSingleton.Create;
begin
  inherited;
  fData := 'hello world';
end;

procedure TSingleton.PrintData;
begin
  writeln('>> PrintData');
  Writeln(fData);
end;

end.
unit sing2; //second singleton

{$mode objfpc}{$H+}

interface

uses
   sing;

type

TSingleton2 = class(TSingleton)
private
  fData2 : string;
protected
  constructor Create;
public
  procedure PrintData; override;
end;

function GetSingleton2 : TSingleton2;

implementation

var
  asing2 : TSingleton2 = nil;

function GetSingleton2 : TSingleton2;
begin
  if asing2 = nil then
    asing2 := TSingleton2.Create;
  Result := asing2;
end;

constructor TSingleton2.Create;
begin
  inherited;
  fData2 := 'hello world 2';
end;

procedure TSingleton2.PrintData;
begin
  inherited;
  Writeln(fData2);
end;

end.
program singtest; //test program

{$mode objfpc}{$H+}

uses
  sing, sing2;

var
  c : char;
  s: TSingleton;

begin

  GetSingleton.PrintData;
  WriteLn('---------');
  GetSingleton2.PrintData;
  WriteLn('---------');
  s := TSingleton.Create;
  s.PrintData;
  s.Free;
  ReadLn(c);

  GetSingleton.Free;
  GetSingleton2.Free;

end. 
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to