Recent

Author Topic: Constructor should be public.  (Read 6386 times)

Frederic Da Vitoria

  • Jr. Member
  • **
  • Posts: 73
Constructor should be public.
« on: June 28, 2013, 12:00:41 pm »
Hello,

What is the rationale for this hint? I understand that usually constructors and destructors are public, but why *should* they be public?
davitof
Lazarus 1.0.10 + FPC 2.6.2 / Windows7 64bits

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Constructor should be public.
« Reply #1 on: June 28, 2013, 12:12:07 pm »
Constructors are called from the main program and other units. If you wish to execute some modular thing within class, you can make private procedures and call them.

Dibo

  • Hero Member
  • *****
  • Posts: 1057
Re: Constructor should be public.
« Reply #2 on: June 28, 2013, 12:21:01 pm »
What is the rationale for this hint? I understand that usually constructors and destructors are public, but why *should* they be public?
So how do you want create object if its constructor is hidden?

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Constructor should be public.
« Reply #3 on: June 28, 2013, 12:28:12 pm »
If you have two classes (TMainClass and TSubClass) in one unit and TSubClass is used only inside TMainClass and nowhere else, then you really don't need public constructor. But it is a special case. In such case you can use nested class.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Frederic Da Vitoria

  • Jr. Member
  • **
  • Posts: 73
Re: Constructor should be public.
« Reply #4 on: June 28, 2013, 12:35:11 pm »
What if I don't want other units to create and destroy objects? Of course, if a unit contains the description of only one class, the constructor and destructor will necessarily be called from outside, so that they must be public. But I often build units with an "elementary" class and a specialized container class. Then it makes sense to make the constructor private: the container class is the only in charge of creating or destroying instances, but the instances may be otherwise manipulated by the rest of the application. This way of doing things helps me ensure I don't forget to destroy an instance.

Edit: I meant "container" in the technical sense, like a TObjectList descendant.
« Last Edit: June 28, 2013, 12:51:19 pm by Frederic Da Vitoria »
davitof
Lazarus 1.0.10 + FPC 2.6.2 / Windows7 64bits

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Constructor should be public.
« Reply #5 on: June 28, 2013, 04:18:52 pm »
Anything you define in the interface section can be seen from other units that use it. Another way to make privacy, is to split some types in a sub unit. If on the otherhand these sub-classes would need something from the others aswell, you can avoid circular references by making yet another unit for common types.

Kind of like:
TApplication
- inherits from CustApp.TCustomApplication
- - inherits from classesh.TComponent
+ many other units that includes classesh for TComponent. LCLClasses.TLCLComponent for specialiced components, and so on.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12768
  • FPC developer.
Re: Constructor should be public.
« Reply #6 on: June 28, 2013, 04:41:53 pm »
What if I don't want other units to create and destroy objects?

You can't anyways There is always a default constructor and destructor..

Closest is to declare an interface with all externally callable symbols, and only export that, and keep the class in the implementation
 

Frederic Da Vitoria

  • Jr. Member
  • **
  • Posts: 73
Re: Constructor should be public.
« Reply #7 on: June 30, 2013, 09:27:12 pm »
All those years, since Delphi didn't complain, I thought my idea worked. I now understand that I can't hide the constructor or destructor, because you can't reduce the visibility of a member. If the ancestor Create was public (which is the case for all TObject descendants), then there is no way you can hide it. What I achieved is actually worse: if by any chance I called Foo's Create from outside the unit, I would unknowingly be directly calling TObject's Create and not Foo's Create.

Thanks to Lazarus for showing me that my trick was useless. And thank you all for showing me to see this was indeed so.
davitof
Lazarus 1.0.10 + FPC 2.6.2 / Windows7 64bits

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Constructor should be public.
« Reply #8 on: June 30, 2013, 11:28:46 pm »
Here is a fast patch that does what you want
Code: [Select]
Unit Unit1;
interface
uses Classes, Types, ......
Type

  TMyInternalyCreatedObject = Class
  Protected
    Constructor PrivateCreate;
  public
    Constructor Create;
  end;

implementation

constructor TMyInternalyCreatedObject.PrivateCreate;
begin
   Inherited Create;
end;

Constructor TMyInternalyCreatedObject.Create;
begin
  Raise Exception.Create('This object is only for internal use.');
end;

Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Frederic Da Vitoria

  • Jr. Member
  • **
  • Posts: 73
Re: Constructor should be public.
« Reply #9 on: July 01, 2013, 09:55:34 am »
Yes, I was thinking of something like this. My idea was using assertions, raising an exception is probably best, because I can't be sure I will test all possible combinations, the issue might arise during a user run.
davitof
Lazarus 1.0.10 + FPC 2.6.2 / Windows7 64bits

 

TinyPortal © 2005-2018