Program demo_for_forum;
{$mode objfpc}{$H+}
Uses
Classes, SysUtils;
Type
util_class = Class // this could be anywhere, including a general utility in a unit, so long as referenced in Uses
// note: unless specifically creating objects or setting vars, there is no need for Create and Destroy, they are done in the background
a_str : String; // by default vars and methods are public, but if uncertain, no harm adding
Procedure set_str( Const s : String );
End;
main_class = Class // this could be a form
Private // data - I have the sections placed into folding, so by labelling each section, I can easily see what each section is when class is folded
Type
nested_class = Class( util_class ) // now this is nested, ie only exists in the class
the_host : main_class; // I use this linkage all the time in my nested classes - the huge advantage is no changes are required to the original class
Procedure call_show_str; // this is going to call back up to the host
End;
Var
nested_obj : nested_class; // note this is now the extended name, not the original util class
Public // methods
Constructor Create;
Destructor Destroy; Override;
Procedure show_str; // this will use the nested string
Procedure main_call; // whatever front end is in place
End;
// main - when I have several classes in unit, I usually put a simple comment line to denote each class code and ensure all code goes in the right section, mainly for folding
Constructor main_class.Create; // if this is for a form, place this code in form Create, or similar, so long as in control of create and free
Begin
nested_obj := nested_class.Create; // because the var, nested_obj, is in the main class, just normal access
nested_obj.the_host := Self; // this is the linkage line, now the nested has access to the host class by using the_host
End;
Destructor main_class.Destroy;
Begin
{ if I have created the objected in Create then I know this is good, if I don't know for sure I either use a boolean flag (var), eg object_set_up,
or set var to Nil in Create and then test If object <> Nil Then FreeAndNil
}
FreeAndNil( nested_obj ); // if not freed it will cause a memory leak, good practice to test heap occasionally
End;
Procedure main_class.main_call;
Begin
nested_obj.set_str( 'demo of nested' ); // note that since nested is now a standard object, the dot is used (if you just put the dot you will get the list up)
show_str;
End;
Procedure main_class.show_str;
Begin
WriteLn( nested_obj.a_str ); // this is possible because a_str in public, play around with that
End;
// main - nested
Procedure main_class.nested_class.call_show_str; // note the way this is set up, since nested_class does not exist by itself, it has be declared as part of main
Begin
the_host.show_str; // this is the link back in action, it could be anything, a var, a label on a form (I often use that), etc. The dot list will show what is accessible.
End;
// nested - note this could be a in unit, just here for convenience
Procedure util_class.set_str( Const s : String ); // note the call here, since nested class only exists in main, it is only recognised within that
Begin
a_str := 'this is util class: string = ' + s; // just to show it was adapted
End;
// general
Procedure demo_of_nested_class;
Var
main_obj : main_class; // for forms obviously don't need this bit
Begin
main_obj := main_class.Create; // because the nested is set up in Create, it now exists - again, not nec in forms
main_obj.main_call; // whatever the main routine is
FreeAndNil( main_obj );
End;
Begin
demo_of_nested_class;
WriteLn; WriteLn('Finished...'); ReadLn; // just stops the console window disappearing automatically
End.