Recent

Author Topic: Why do procedures used in Units accessed outside need to be "class procedures.."  (Read 1117 times)

Derz

  • New Member
  • *
  • Posts: 33
I just created a unit containing a class ("object") with Procedures and Functions meant to be called from outside.

Ie..
Code: Pascal  [Select][+][-]
  1. Unit MyUnit;
  2.  
  3. {$MODE OBJFPC} {$H+}
  4.  
  5. interface
  6. type
  7.   TMyClass = class
  8. Private
  9.   procedure CreateKey();
  10.   function Do():Boolean;
  11.   var Var1:String;
  12. public  
  13.   procedure Initialize(aPassword:string);
  14.   procedure Set(aVar:String)
  15.   function Get():String;
  16.   end;
  17.  
  18.   MyClass1 = type TMyClass;
  19.    
  20. implementation
  21.  ...  
  22.  

And, I found that when I need to use the functions/procedures in another unit..
Ie..
Code: Pascal  [Select][+][-]
  1. ..
  2.   MyClass1.Initialize('MyPassword');
  3. ..
  4.  

I get errors like
  "Only class methods, class properties and class variables can be accessed (or referenced) in class methods"

The only way I found to correct this is to define every Procedure, Function (Public or Private) and Variable inside MyClass as a "class"
Ie..
Code: Pascal  [Select][+][-]
  1. type
  2.   TMyClass = class
  3. Private
  4.   Class procedure CreateKey();
  5.   Class function Do():Boolean;
  6.   Class var Var1:String;
  7. public  
  8.   Class procedure Initialize(aPassword:string);
  9.   Class procedure Set(aVar:String)
  10.   Class function Get():String;
  11.   end;
  12.  
  13.   MyClass1 = type TMyClass;
  14.    
  15. implementation
  16.  ...  

I searched but could not find why these procedures, functions and variables need to be defined as classes themselves.  Documentation on creating units with classes do not mention this requirement.  Should I be doing this differently?


« Last Edit: August 04, 2025, 12:47:48 am by Derz »

Mike.Cornflake

  • Hero Member
  • *****
  • Posts: 1269
You see the Private and Public definitions?  They're there for precisely this:

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyClass = class
  3. Private
  4.   procedure Create();

You've put your Create inside Private.  That means only code in that particular unit has access to the create. 
If you want code in other units to access the Create(), then move the function call into Public instead. 

For Create, this is always a good idea.

None of your routines look like they should be Class routines.  And I'm a little perplexed that Class Create could be called from outside this unit.  So really, best to remove all those Class prefixes, go back to your original code, and just move the Create to Public.
« Last Edit: August 03, 2025, 09:53:14 pm by Mike.Cornflake »
Lazarus Trunk/FPC latest fixes on Windows 11
  I'm getting old and stale.  Slowly getting used to git, I'll get there...

jamie

  • Hero Member
  • *****
  • Posts: 7586
You need to implement the CONSTRUCTOR and it needs to be done in the unit where you are using it.


In the unit where you are using it;

Code: Pascal  [Select][+][-]
  1. Var
  2.  MyClass:TMyClass
  3.  
  4. Implementation
  5. //Somewhere  in code land
  6.  
  7. MyClass := TMyClass.Create;
  8.  
  9. //From there, you acces the fields, methods etc via the MyClass.
  10.  
  11.  

 Also need to Call the Free of your myClass.Free at some point so the destructor will be called.

Jamie
The only true wisdom is knowing you know nothing

Derz

  • New Member
  • *
  • Posts: 33
Thank you Jamie and Mike for your replies. 

I am sorry that in my original post, now edited, I had overridden the object create procedure and made it private.  This was an oversite to simplify the actual code.  However, the functions and procedures called from other units are all in the PUBLIC section of the unit/class declaration.

I followed the advice of jamie and created a variable of TMyClass in the calling unit and that worked.
I was then able to remove all the "class identifiers" from the procedures, functions and variables in the called unit class.

Thank you!


PascalDragon

  • Hero Member
  • *****
  • Posts: 6344
  • Compiler Developer
And, I found that when I need to use the functions/procedures in another unit..
Ie..
Code: Pascal  [Select][+][-]
  1. ..
  2.   MyClass1.Initialize('MyPassword');
  3. ..
  4.  

I get errors like
  "Only class methods, class properties and class variables can be accessed (or referenced) in class methods"

Non-class or “instance” methods need to be used together with an instance, thus a variable or field of the type of the class and not the class type itself. And to create an instance you must use a constructor (though it doesn't need to be called Create except if you want to inherit from an existing class and override its existing constructor.

Also the type alias is rather useless. You can just use TMyClass.

 

TinyPortal © 2005-2018