Recent

Author Topic: Define class in unit without other units being capable  (Read 1249 times)

wildfire

  • Full Member
  • ***
  • Posts: 110
Define class in unit without other units being capable
« on: March 02, 2023, 07:31:40 pm »
Hi guys and gals,

Ok I'm cutting to the quik, here's what I want to do...

Can I create a class in a unit without any other unit or program being able to create another instance of that class?

The Idea is to create the instance in the initialization section and destroy it in the finalization section. However I don't want other units to be able to create other instances of the class, as far as they are concerned "uses uExample" then an instance is available... e.g.

Code: [Select]
type
  tExample: class          // I don't want other units to have the ability to create tExample.
    public
      msg: string
  end;
 
var
    MyExample: tExample;       // I do want other units to have access to MyExample.
I have thought about a forward declaration to define the class in the implementation section or to put the constructor in the private defination of the class but OOP is fairly new to me so I thought, best ask the experts... What would you do
A halo is a mere circle, when does it end?

Thaddy

  • Hero Member
  • *****
  • Posts: 18764
  • To Europe: simply sell USA bonds: dollar collapses
Re: Define class in unit without other units being capable
« Reply #1 on: March 02, 2023, 08:01:02 pm »
When you only want to use that class in only that unit, you are on the right track: Just declare it in the implementation section. If you want to use that class instance from other units it gets more complex.
« Last Edit: March 02, 2023, 08:06:25 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Define class in unit without other units being capable
« Reply #2 on: March 02, 2023, 08:13:30 pm »
It's called singleton. Here's ten years old topic: https://forum.lazarus.freepascal.org/index.php/topic,19761.0.html - the first post.

If someone will try to create a new instance, he will get already existing instance (if exists).
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/

cdbc

  • Hero Member
  • *****
  • Posts: 2664
    • http://www.cdbc.dk
Re: Define class in unit without other units being capable
« Reply #3 on: March 02, 2023, 08:37:12 pm »
Hi
I would declare an interface in the interface section and then implement it in the implementation section:
Code: Pascal  [Select][+][-]
  1. interface
  2. const SGUIDIExample = '{CFB68445-3868-46CA-8E02-00266B891710}';
  3. type
  4. {$interfaces corba} { NO reference counting! }
  5.   IExample = interface[SGUIDIExample]  
  6.     function get_msg: string;
  7.     procedure set_msg(aValue: string);
  8.     property msg: string read get_msg write set_msg;
  9.   end;
  10. {$interfaces com} { reference counted! }
  11. var
  12.     MyExample: IExample;
  13. implementation
  14. type
  15.   TExample = class(TObject,IExample)
  16.   private
  17.     fmsg: string;
  18.     function get_msg: string;
  19.     procedure set_msg(aValue: string);
  20.   public
  21.     property msg: string read get_msg write set_msg;
  22.   end;
  23.  
  24. var LocExample: TExample;
  25.  
  26. function TExample.get_msg: string;
  27. begin
  28.   result:= fmsg;
  29. end;
  30.  
  31. procedure TExample.set_msg(aValue: string);
  32. begin
  33.   fmsg:= aValue;
  34. end;
  35.  
  36. initialization
  37.   LocExample:= TExample.Create;
  38.   LocExample.GetInterface(SGUIDIExample,MyExample);
  39.  
  40. finalization
  41.   LocExample.Free;
  42. end.
  43.  
Something along these lines... (Untested code)
Hth - Regards Benny
« Last Edit: March 02, 2023, 08:42:31 pm by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

Thaddy

  • Hero Member
  • *****
  • Posts: 18764
  • To Europe: simply sell USA bonds: dollar collapses
Re: Define class in unit without other units being capable
« Reply #4 on: March 02, 2023, 09:18:41 pm »
It's called singleton. Here's ten years old topic: https://forum.lazarus.freepascal.org/index.php/topic,19761.0.html - the first post.

If someone will try to create a new instance, he will get already existing instance (if exists).
It is NOT called a singleton if the class can be instanciated in the same unit more than once(eg. in a loop)
A singleton is a completely different pattern, although OP might not have his theory right.
Comes to mind the old Delphi grids.pas where that happens all the time. (multiple local instances of a cell object)
Hi
I would declare an interface in the interface section and then implement it in the implementation section:
Something along these lines... (Untested code)
Hth - Regards Benny
That won't work, since you can not instanciate the class. Better test it.. ;D
What IS possible is to declare a variable as an interface in the interface section and initialize it. You can't inherit from that easily. But you probably end up with an interface that needs to implement every public method in the class! And as/is is not possible, since you can not reference the class.
« Last Edit: March 02, 2023, 09:25:06 pm by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

cdbc

  • Hero Member
  • *****
  • Posts: 2664
    • http://www.cdbc.dk
Re: Define class in unit without other units being capable
« Reply #5 on: March 02, 2023, 10:18:04 pm »
Hi
@Thaddy: You're right, it's best to test, so i did.
Here's a little something i cooked up for you...
Hth - Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

wildfire

  • Full Member
  • ***
  • Posts: 110
Re: Define class in unit without other units being capable
« Reply #6 on: March 03, 2023, 08:34:12 am »
Thanks guys,

I'll take some time to digest the information supplied, I'm sure a solution is in there somewhere.

Thanks again and if anyone has any further input I'm all ears.
A halo is a mere circle, when does it end?

Thaddy

  • Hero Member
  • *****
  • Posts: 18764
  • To Europe: simply sell USA bonds: dollar collapses
Re: Define class in unit without other units being capable
« Reply #7 on: March 03, 2023, 10:18:29 am »
Hi
@Thaddy: You're right, it's best to test, so i did.
Here's a little something i cooked up for you...
Hth - Regards Benny
Thaddy is right, because what you do is a copy operation to a variable in the interface section. That is not only cheating, it is plain wrong if you want create a class instance from an interface reference. Your code works only by accident.

My point is, stupid CORBA or not, you can't do this:
Code: [Select]
unit stupid;
{$mode objfpc}{$interfaces CORBA}
interface
type
  IMyInterface:IInterface;
var
   MyInterface: TMyInterface;
implementation
   TMyClass = class(Tobject,IMyInterface);
end.
Code: Pascal  [Select][+][-]
  1. Program stupiddemo;
  2. {$mode objfpc}{$interfaces CORBA}
  3. uses stupid;
  4. var
  5.   SomeInterface:TMyInterface;
  6. begin
  7.   SomeInterface := TMyClass.Create as TMyInterface; // error
  8.   SomeInterface := MyInterface;
  9.   writeln((SomeInterface as TMyClass).Classname);  // BOOM
  10. end.

If you want to cheat, plz do so, but actually you are indirectly exposing information that should stay hidden as per the question.  ;D
« Last Edit: March 03, 2023, 10:47:01 am by Thaddy »
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

 

TinyPortal © 2005-2018