Implementing a true Singleton - Can we decrease the visibility of a method?

classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Implementing a true Singleton - Can we decrease the visibility of a method?

Graeme Geldenhuys-2
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'

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

sing.pas (788 bytes) Download Attachment
sing2.pas (832 bytes) Download Attachment
singtest.pas (454 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Vincent Snijders
Graeme Geldenhuys schreef:

> 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!

Maybe I am analyzing your output wrong, but to me it seems as if the contructor of
TObject is called in the third case. printdata seems to print an empty text.

So the protected contructor is unreachable, but the public constructor in TObject
remains public.

Vincent
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Graeme Geldenhuys-2
On 12/8/06, Vincent Snijders <[hidden email]> wrote:
> Maybe I am analyzing your output wrong, but to me it seems as if the contructor of
> TObject is called in the third case. printdata seems to print an empty text.
>
> So the protected contructor is unreachable, but the public constructor in TObject
> remains public.

That's correct, which is even worse.  It gives us a half-baked object.
fData is never initialized.  Putting a writeln() statement inside
TSingleton.Create shows that on the 3rd instance it is never executed.

[graemeg-linux] singleton > ./singtest
>> Tsingleton.Create
>> PrintData
hello world
---------
>> Tsingleton.Create
>> PrintData
hello world
hello world 2
---------
>> PrintData



--
Graeme Geldenhuys

There's no place like S34° 03.168'  E018° 49.342'
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Vincent Snijders
Graeme Geldenhuys schreef:

> On 12/8/06, Vincent Snijders <[hidden email]> wrote:
>> Maybe I am analyzing your output wrong, but to me it seems as if the
>> contructor of
>> TObject is called in the third case. printdata seems to print an empty
>> text.
>>
>> So the protected contructor is unreachable, but the public constructor
>> in TObject
>> remains public.
>
> That's correct, which is even worse.  It gives us a half-baked object.
> fData is never initialized.  Putting a writeln() statement inside
> TSingleton.Create shows that on the 3rd instance it is never executed.
>

I think the solution is to create a public constructor which throws an
NotImplemented exception or something like that.

Then you create a protected (or private) constructor
constructor CreateSingletonInstance;
which is accessible only in that unit.

Note: instead of making function GetSingleton : TSingleton; a global function you
could make it class function GetInstance too.

Vincent
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Graeme Geldenhuys-2
On 12/8/06, Vincent Snijders <[hidden email]> wrote:
> I think the solution is to create a public constructor which throws an
> NotImplemented exception or something like that.

Ok, that works, or at least stops a developer from trying to create a
instance directly.  In the exception message, I mention the correct
function they should have used.

> Note: instead of making function GetSingleton : TSingleton; a global function you
> could make it class function GetInstance too.

Yes I know, thanks. But I prefer to use the function, as it is less
typing, especially when the class name is lengthy.  I also normally
prefix it with a 'g' to show it is a global singleton function.

gLog
    vs
TLogToFile.GetSingleton

When you use singletons a lot (as I do), less typing is better.  :)

PS:
  I still don't know why we can't decrease visibility in Free Pascal.
Is there some internal language design that prevents it?

--
Graeme Geldenhuys

There's no place like S34° 03.168'  E018° 49.342'
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Jonas Maebe-2

On 8 dec 2006, at 10:55, Graeme Geldenhuys wrote:

>  I still don't know why we can't decrease visibility in Free Pascal.
> Is there some internal language design that prevents it?

At least Borland explicitly says you cannot do that:
   http://info.borland.com/techpubs/delphi/delphi5/oplg/classes.html

"You can increase the visibility of a member in a descendant class by  
redeclaring it, but you cannot decrease its visibility. For example,  
a protected property can be made public in a descendant, but not  
private. Moreover, published members cannot become public in a  
descendant class."


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

TOndrej
In reply to this post by Graeme Geldenhuys-2
On 12/8/06, Graeme Geldenhuys <[hidden email]> wrote:
> I still don't know why we can't decrease visibility in Free Pascal.
> Is there some internal language design that prevents it?

A class definition (or at least its parts visible from outside) can be
understood as a kind of contract. If you have a class TDog with a
public property Tail then, by definition, any TDog descendant
(TBulldog, TLabrador, TDingo etc.) must have the public property Tail.
Otherwise they wouldn't be TDog but something else, again by
definition.

I'm not even sure if there is a language which allows demoting
visibility of inherited class members. It would seem odd to me. Just
my 2c, of course. ;-)

HTH
TOndrej
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Graeme Geldenhuys-2
On 12/8/06, TOndrej <[hidden email]> wrote:
> On 12/8/06, Graeme Geldenhuys <[hidden email]> wrote:
> > I still don't know why we can't decrease visibility in Free Pascal.
> > Is there some internal language design that prevents it?
>
> A class definition (or at least its parts visible from outside) can be
> understood as a kind of contract. If you have a class TDog with a
> public property Tail then, by definition, any TDog descendant

I understand your example and that makes sense, but would be handy in
certain cases to change it.

> I'm not even sure if there is a language which allows demoting
> visibility of inherited class members. It would seem odd to me. Just
> my 2c, of course. ;-)

C++, C#, VB.Net are three I know of.  I think Java also allows it.


--
Graeme Geldenhuys

There's no place like S34° 03.168'  E018° 49.342'
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Jonas Maebe-2

On 8 dec 2006, at 13:44, Graeme Geldenhuys wrote:

>> I'm not even sure if there is a language which allows demoting
>> visibility of inherited class members. It would seem odd to me. Just
>> my 2c, of course. ;-)
>
> C++, C#, VB.Net are three I know of.

http://msdn2.microsoft.com/en-us/library/ms182332(VS.80).aspx

Quote:

"You should not change the access modifier for inherited members."

So it's possible but discouraged, and they give warnings (and  
sometimes errors) for it with the recommendation "Do not exclude a  
warning from this rule."

As far as I understand the text on that page, the only case where  
it's considered "safe" is if the the method/class is declared  
"final". We do not have final methods/classes in Object Pascal, and  
such final methods/classes are often considered a cause of problems  
in themselves (because you can bet sooner or latter someone will have  
some need to override/inherit anyway).


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Graeme Geldenhuys-2
On 12/8/06, Jonas Maebe <[hidden email]> wrote:
> Quote:
>
> "You should not change the access modifier for inherited members."
>
> So it's possible but discouraged, and they give warnings (and
> sometimes errors) for it with the recommendation "Do not exclude a
> warning from this rule."

There is a lot of things in life we shouldn't do, but we do.  :-)
At least give us the choice, maybe via a compiler directive and keep
the compiler warning in place.  That way we can use it responsibly
when required, as in the case of implementing a true singleton. I'm
sure there are more examples. As it stands currently (my sample
singleton code) the developer can still screw up by creating a new
instance instead of going through the global function.

--
Graeme Geldenhuys

There's no place like S34° 03.168'  E018° 49.342'
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Vincent Snijders
Graeme Geldenhuys schreef:

> On 12/8/06, Jonas Maebe <[hidden email]> wrote:
>> Quote:
>>
>> "You should not change the access modifier for inherited members."
>>
>> So it's possible but discouraged, and they give warnings (and
>> sometimes errors) for it with the recommendation "Do not exclude a
>> warning from this rule."
>
> There is a lot of things in life we shouldn't do, but we do.  :-)
> At least give us the choice, maybe via a compiler directive and keep
> the compiler warning in place.  That way we can use it responsibly
> when required, as in the case of implementing a true singleton. I'm
> sure there are more examples. As it stands currently (my sample
> singleton code) the developer can still screw up by creating a new
> instance instead of going through the global function.
>

I think it cannot be prevented.

Suppose you could hide the constructor and TSingleton.Create was not
visible, I still could create a TSingleton object and call the
TObject.Create on it.

var
   Singleton1, Singleton2: TSingleton;
begin
   Singleton1 := TSingleton.CreateInstance;
   TObject(Singleton1).Create;
   Singleton2 := TSingleton.CreateInstance;
   TObject(Singleton).Create;
   // now there are two Singleton objects.
end.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Jonas Maebe-2
In reply to this post by Graeme Geldenhuys-2

On 8 dec 2006, at 14:03, Graeme Geldenhuys wrote:

> There is a lot of things in life we shouldn't do, but we do.  :-)
> At least give us the choice, maybe via a compiler directive and keep
> the compiler warning in place.  That way we can use it responsibly
> when required,

This is a generic argument which you can use in support of pretty  
much any relaxing of semantic/syntax rules.

> as in the case of implementing a true singleton. I'm
> sure there are more examples. As it stands currently (my sample
> singleton code) the developer can still screw up by creating a new
> instance instead of going through the global function.

This particular issue is caused by the fact that in Delphi-style  
Object Pascal classes automatically inherit from TObject, which has a  
public constructor. And if you override the constructor with your  
own, they no longer can do that either (although it's obviously a run  
time and not compile time check).

One thing that could be changed is the compile so that you get a  
compile-time error if you try

type
   tc = class
     constructor create; virtual; abstract;
   end;

var
   c: tc;
begin
   c := tc.create
end.

(currently this compiles with only a warning about the fact that tc  
has abstract methods)


It would however still only give a run time error if you'd instead do

type
   tc = class
     constructor create; virtual; abstract;
   end;

  ttc = class of tc;

var
   cc: ttc;
   c: tc;
begin
   cc := tc;
   c := cc.create;
end.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

TOndrej
In reply to this post by Graeme Geldenhuys-2
> > I'm not even sure if there is a language which allows demoting
> > visibility of inherited class members. It would seem odd to me. Just
> > my 2c, of course. ;-)
>
> C++, C#, VB.Net are three I know of.  I think Java also allows it.

In these languages, AFAIK, it's allowed, the compiler generates a
warning, but the visibility does not actually change. You would still
be able to access the member, if not directly on a variable of the
descendant type then certainly by typecasting to the ancestor type.

HTH
TOndrej
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Steve Williams-3
In reply to this post by Graeme Geldenhuys-2
> 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.  :-(

Try this.
http://bdn.borland.com/article/22576

--
Sly




This message and its attachments may contain legally privileged or confidential information. This message is intended for the use of the individual or entity to which it is addressed. If you are not the addressee indicated in this message, or the employee or agent responsible for delivering the message to the intended recipient, you may not copy or deliver this message or its attachments to anyone. Rather, you should permanently delete this message and its attachments and kindly notify the sender by reply e-mail. Any content of this message and its attachments, which does not relate to the official business of the sending company must be taken not to have been sent or endorsed by the sending company or any of its related entities. No warranty is made that the e-mail or attachment(s) are free from computer virus or other defect.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease thevisibility of a method?

Matt Emson
In reply to this post by Jonas Maebe-2

> On 8 dec 2006, at 10:55, Graeme Geldenhuys wrote:
>
> >  I still don't know why we can't decrease visibility in Free Pascal.
> > Is there some internal language design that prevents it?
>
> At least Borland explicitly says you cannot do that:
>    http://info.borland.com/techpubs/delphi/delphi5/oplg/classes.html

Delphi 5 onwards generates a hint for each method that is of a lower
visibility thatn its ancestors implementation.

I've used the following to implement a singleton before:

unit x;

interface

type
  ISingleton = interface [-----GUID GOES HERE-----]
    procedure SingletonAction;
  end;

var
  MySingleton: ISingleton;

implementation

type
  TSingleton = class(TInterfacedObject, ISingleton)
  private
     procedure SingletonAction;
  end;

   procedure TSingleton .SingletonAction;
   begin
       [....]
   end;

initialization
   MySingleton := TSingleton.Create;

finalization
    MySingleton := nil;

end.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Michael Van Canneyt
In reply to this post by Steve Williams-3


On Fri, 8 Dec 2006, Steve Williams wrote:

> > 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.  :-(
>
> Try this.
> http://bdn.borland.com/article/22576

Maybe we should include an implementation in FPC by default ?

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Andreas Berger
In reply to this post by Graeme Geldenhuys-2


Graeme Geldenhuys wrote:

> On 12/8/06, TOndrej <[hidden email]> wrote:
>> On 12/8/06, Graeme Geldenhuys <[hidden email]> wrote:
>> > I still don't know why we can't decrease visibility in Free Pascal.
>> > Is there some internal language design that prevents it?
>>
>> A class definition (or at least its parts visible from outside) can be
>> understood as a kind of contract. If you have a class TDog with a
>> public property Tail then, by definition, any TDog descendant
>
> I understand your example and that makes sense, but would be handy in
> certain cases to change it.
A TBoxer could be considered a TDog without a tail :)
>
>> I'm not even sure if there is a language which allows demoting
>> visibility of inherited class members. It would seem odd to me. Just
>> my 2c, of course. ;-)
>
> C++, C#, VB.Net are three I know of.  I think Java also allows it.
Yes, but that causes other problems. I worked for a time for a company
that wrote programs for aeronautical equipment. In these cases the above
mentioned languages could not be used. C was ok, and C++ could only be
used if you followed very strict rules (and a lint program to guarantee
you were following the rules). Pascal however had far fewer restrictions
(almost none if I remember correctly). Modula-2 could be freely used. If
we relax the Pascal rules we will end up with a non-secure language like
the above.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Marc Santhoff
In reply to this post by Graeme Geldenhuys-2
Am Freitag, den 08.12.2006, 10:50 +0200 schrieb Graeme Geldenhuys:

> 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.

One working solution is to use a global var. This is bad but acceptable
for a singleton imo. If would be nice if the variable could be hidden.
Smth like this:

...
var
        _mySingleton: TSingleton;


constructor TSingleton.create;
begin
        if not(assigned(_mySingleton)) then
        begin
                inherited;
                ... do initializations ...
                _mySingleton := self;
        end;
end;

initilization
        _mySingleton := NIL;
end.

HTH,
Marc


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Micha Nelissen
In reply to this post by Michael Van Canneyt
Michael Van Canneyt wrote:
>> Try this.
>> http://bdn.borland.com/article/22576

NewInstance/FreeInstance is what I would have recommended as well.

> Maybe we should include an implementation in FPC by default ?

How ? The article works as-is AFAIK.

Btw, I think singletons are nonsense too. Why is a global variable evil,
and a singleton class not ?

Micha
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Implementing a true Singleton - Can we decrease the visibility of a method?

Bugzilla from daniel.mantione@freepascal.org


Op Fri, 8 Dec 2006, schreef Micha Nelissen:

> Btw, I think singletons are nonsense too. Why is a global variable evil,
> and a singleton class not ?

Well, a singleton can hide and/or protect its private data.

Actually, a unit is a singleton. The procedures are the methodes, the
interface declares the public methode and the implementation the private
methods. The constructor is the initialization section and the destructor
the finalization section.

But, in pure OOP the unit concept does not exist. I interpret the
singleton as the OOP equivalent of the unit.

Daniël
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
12