Discussion:
Private constructor
(too old to reply)
Jatin
2006-03-01 06:14:40 UTC
Permalink
Is it possible in Delphi to make default constructor hidden such that
caller can't call it? Even if I declare it to be private, the TObject's
default constructor is still visible to the caller, which I want to
avoid. Basically what I want to achieve is that caller should only be
able to instantiate the object by calling its non-default constructor.
Is there any other wy to achieve that? I will appreciate any comments
and suggestions.

Thanks,

Jatin
====================
Nicholas Sherlock
2006-03-01 06:40:47 UTC
Permalink
Post by Jatin
Is it possible in Delphi to make default constructor hidden such that
caller can't call it? Even if I declare it to be private, the TObject's
default constructor is still visible to the caller, which I want to
avoid. Basically what I want to achieve is that caller should only be
able to instantiate the object by calling its non-default constructor.
Is there any other wy to achieve that? I will appreciate any comments
and suggestions.
If I understand you correctly, this is already default behaviour:

TMyObj=class
public
constructor create(s:string);
end;

procedure TForm1.Button1Click(Sender: TObject);
var obj:TMyObj;
begin
obj:=TMyObj.create;
end;

Will not compile, since there /is/ no default TObject constructor.

Cheers,
Nicholas Sherlock
Jatin
2006-03-01 07:30:47 UTC
Permalink
Post by Nicholas Sherlock
TMyObj=class
public
constructor create(s:string);
end;
procedure TForm1.Button1Click(Sender: TObject);
var obj:TMyObj;
begin
obj:=TMyObj.create;
end;
Will not compile, since there /is/ no default TObject constructor.
Cheers,
Nicholas Sherlock
Yes, you are right, it doesn't compile. But when I declare a private
constructor, it does compile. Apparently, the default constructor listed
by the Code-insight which I mentioned in my original post was my class'
own private constructor.

Why so? Private should make default ctor invisible, right? See below:

type
TMyClass = class
private
m_str : String;
constructor Create; // <-- private
public
constructor Create(S : String);
end; //class



{ TMyClass }

constructor TMyClass.Create(S: String);
begin
m_str := s;
end;

var
pMyObj : TMyClass;

constructor TMyClass.Create;
begin
//
end;

begin //main
pMyObj := TMyClass.Create; // <-- compiles
end. //main
Nicholas Sherlock
2006-03-01 08:32:49 UTC
Permalink
Private members are visible to all other classes or routines in the same
unit. Move your class to another unit.

Cheers,
Nicholas Sherlock
Jatin
2006-03-02 06:18:11 UTC
Permalink
Post by Nicholas Sherlock
Private members are visible to all other classes or routines in the same
unit. Move your class to another unit.
Cheers,
Nicholas Sherlock
I moved the class to another unit, and removed the declaration and
implementation of default constructor Create. I am still able to see the
Create constructor from the main program - at least code-insight shows
it. This Create must be that of TObject's. Probably Delphi traverses the
ancestry to find the default default constructor and make it available.

Jatin
============
Nicholas Sherlock
2006-03-02 09:11:56 UTC
Permalink
Post by Jatin
Post by Nicholas Sherlock
Private members are visible to all other classes or routines in the
same unit. Move your class to another unit.
Cheers,
Nicholas Sherlock
I moved the class to another unit, and removed the declaration and
implementation of default constructor Create. I am still able to see the
Create constructor from the main program - at least code-insight shows
it. This Create must be that of TObject's. Probably Delphi traverses the
ancestry to find the default default constructor and make it available.
You're right, confirmed Delphi 5. To me, this looks like a Delphi bug.
If you have overloaded constructors, then a default constructor is
visible, such as this situation:

type tmyclass=class
public
constructor create(s:string); overload;
constructor create(i:integer); overload;
end;

A possible solution might be to rename one of your constructors, then
you don't have to overload them.

Cheers,
Nicholas Sherlock
Bruce Roberts
2006-03-02 18:16:42 UTC
Permalink
Post by Jatin
I moved the class to another unit, and removed the declaration and
implementation of default constructor Create. I am still able to see the
Create constructor from the main program - at least code-insight shows
it. This Create must be that of TObject's. Probably Delphi traverses the
ancestry to find the default default constructor and make it available.
You're right, confirmed Delphi 5. To me, this looks like a Delphi bug. If
you have overloaded constructors, then a default constructor is visible,
I'm having real trouble seeing how you can view this as a 'bug'.
tObject.Create is a non-virtual, public constructor. It is always going to
be visible unless hidden by a descendant declaring a Public or Published
constructor named Create. Delphi does not have such a thing as a 'default'
constructor.

The behavior when overloading the identifier Create should come as no
surprise, it is exactly the same as what would happen with a similar
construction of methods. You are afterall overloading the identifier, not
hiding it. In otherwords you are telling the compiler that in addition to
the existing definition of the identifier, you want two more definitions of
the same name identified by different parameter lists.

Had tObject.Create been virtual, then you would have needed to use the
reintroduce keyword in addition to overload if you did not want to hide
tObject.Create. If you didn't use reintroduce then tObject.Create would
have been hidden. Exactly the same as any method.

Not a bug at all. In fact the behavior is exactly as one would expect given
the language description in the Delphi / Object Pascal Language Guide/
A possible solution might be to rename one of your constructors, then you
don't have to overload them.
Overloading is rarely, IMO, a good idea. Overloading constructors is a
terrible idea.
Nicholas Sherlock
2006-03-02 18:40:32 UTC
Permalink
Bruce Roberts wrote:
[...]
Post by Bruce Roberts
You are afterall overloading the identifier, not
hiding it. In otherwords you are telling the compiler that in addition to
the existing definition of the identifier, you want two more definitions of
the same name identified by different parameter lists.
Of course, you're right. Don't know what I was thinking :).

Cheers,
Nicholas Sherlock

Rob Kennedy
2006-03-01 06:47:18 UTC
Permalink
Post by Jatin
Is it possible in Delphi to make default constructor hidden such that
caller can't call it? Even if I declare it to be private, the TObject's
default constructor is still visible to the caller, which I want to
avoid. Basically what I want to achieve is that caller should only be
able to instantiate the object by calling its non-default constructor.
If your class's public constructor has the same name as its ancestor's
constructor, then you cannot call the ancestor's constructor on the
descendant class. The new method hides the old one.

It's still possible to call the inherited constructor, but it's cumbersome.
Post by Jatin
Is there any other wy to achieve that? I will appreciate any comments
and suggestions.
If the user calls the wrong constructor, then the class won't work
correctly, right? Thus it seems to be a self-limiting problem.
--
Rob
Tygrys
2006-03-01 20:11:51 UTC
Permalink
Post by Jatin
Is it possible in Delphi to make default constructor hidden such that
caller can't call it? Even if I declare it to be private, the TObject's
default constructor is still visible to the caller, which I want to avoid.
Basically what I want to achieve is that caller should only be able to
instantiate the object by calling its non-default constructor. Is there
any other wy to achieve that? I will appreciate any comments and
suggestions.
You can make it non-working, raising an exception in the default create.
"Exception: Please use Init constructor to build this object" :-)

Hiding it can be harder than that.

Tygrys
Jatin
2006-03-02 06:19:16 UTC
Permalink
Post by Tygrys
You can make it non-working, raising an exception in the default create.
"Exception: Please use Init constructor to build this object" :-)
Hiding it can be harder than that.
How to hide it?

Jatin
============
Tygrys
2006-03-02 09:54:38 UTC
Permalink
Post by Jatin
Post by Tygrys
You can make it non-working, raising an exception in the default create.
"Exception: Please use Init constructor to build this object" :-)
Hiding it can be harder than that.
How to hide it?
AFAIK you can't. You can make your own Create, which will hide TObjects'
Create and your own will make an exception as above.


Tygrys
Continue reading on narkive:
Loading...