----- Original Message -----
From: "Alan Colburn" <[EMAIL PROTECTED]>
To: "Borland's Delphi Discussion List" <[email protected]>
Sent: Friday, May 26, 2006 8:18 PM
Subject: Learning OOP (part 3)
> First, I'm confused now about freeing memory and also about understanding
> what's passed, memory-wise, by parameters in methods ("x:TSomething" vs.
> "var x:TSomething" vs "const x:TSomething") ...
You can pass objects as "var" or as a pointer to the object:
you can return an object from a method which is
initialised within the method itself (eg. a dataset or tperson etc.)
you can test an object for being nil and if so assign memory to it,
so that it is initialised only once, or you can free it and then
reinitialise it
(to avoid memory leaking) or you can have a 'reset' method which resets
default values;
>
> Next, to help me understand OOP, I made a small app. It simply manipulates
> attributes on a list of objects--books in a library, members of a club,
> whatever. I'm using people objects, but it could be anything. I could
> accomplish this task by dropping a few data aware controls on a form,
> connecting them to a dataset, and writing event handlers. To learn, I'm
> approaching the task in a more OOP-centric manner.
Good approach I think!
>
> So, I created a base class (TPerson) with a few attributes, a class to
work
> with groups of TPerson objects (TPeople), and a user interface class
(TGUI).
>
> I also created TPeople.SaveToFile and .LoadFromFile methods, but let's
> suppose I wanted to put the code into another class--someday I could
decide
> to load/save info with a different file format, so it would be good to
have
> persistence stuff separate from everything else.
You could create a descendant object with using overridden methods for
LoadFromFile etc or us OVERLOAD if you want multiple forms of the same
method within the same class (using different parameters)
Use of OVERLOAD and OVERRIDE is very useful!
> Currently, the TGui class creates and ultimately frees a global instance
of
> TPeople. TPeople creates a list of TPerson objects.
>
> Assume that the Save code will iterate through the items in TPeople and
save
> each object's fields. So, I assume that TGui calls TPeople's SaveToFile
> method (passing in a filename string), which in turn calls a method in the
> new class (TPersistTheCollection).
Isn't TPersistTheCollection the parent class? If so TPeople's SaveToFile
would also call the SaveToFile of TPersistTheCollection (if marked
internally as inherited) or not if completely overridden;
>
> Would TPeople.SaveToFile create a new instance of TPersistCollection, and
> iterate through a loop passing each member of the TPeople list to
> TPersistTheCollection (a pointer to the list member? a copy of the
object?),
> and then Free the instance?
The list defined in the parent object should be created only the once, and
remains available in the descendant class: using clear on a tobjectlist
should also free the memory assigned to the objects assigned to the list,
not only the
tobjectlist instance memory; you can save to file and leave the list as it
is (unless you want to wipe the slate clean after saving): the important
thing is to clear the list before loading from a file (I presume you could
do this in the Loadfromfile method)
>
> And then how would the Load method work? What's passed from
> TPersistTheCollection?
>
> Finally, are objects ever used as parameters in methods? If so, where are
> these object instances usually freed?
I often pass an object as a parameter (if I want to assign values to its
internal variables etc): I often use a currentobject (eg currentperson :
tperson;) variable (like a cursor), which here would point to the current
tperson instance in the list (it does not have memory of its own but points
to an initialised tperson instance already in the tpeople list); the
'currentperson : tperson;'
declaration can be made within the public section of Tpeople
so that it will be available to the TGUI instance;
I would have a FindPerson method similar to
currentperson := FindPerson('Joe Bloggs');
The find person method iterates through the person list
for 'Joe Bloggs' and if it finds it the method points to
that tPerson, if not it returns a NIL;
Similarly I have an AppendPerson(NewPerson: tperson);
First you create a new instance of tperson, initialise its values
and then pass it to AppendPerson which will add it to the
end of the list;
You can also create an overloaded version of AppendPerson(name: string;
surname: string) which will create the object internally and append it to
the list;
Similarly for DeletePerson or Update person;
Descendant objects of tperson should be able to be passed as parameters
to any method using a tperson variable;
Another possibility is to create a tFilter class which has a tPeople
as a variable, create an instance of it, assign the tPeople variable to your
instance in tGUI and use its (tFilter) methods for saving and loading to
file, or updating to a database or whatever:
in this way you can derive descendant filters more easily since
the tpeople class and the tfilter class are independant of each other
tGUI could contain both a tPeople instance and a tFilter instance, which are
easily reassignable (for multiple lists or for multiple filter options);
I have been using this mode of thinking in relation to Delphi (and also to
C#)
and it seem a good approach: especially for OOP driven database structures
using different SQL dialects (the data part (tTableObjList) is analogous to
your tpeople and the database/SQL (tSQLfilter) part corresponds to the
tfilter)
I have a tDatabaseObj class which unites the tSQLfilter and the
tTableObjList classes and any methods that I need to add for data
elaboration;
then I have the tGUI part which has ONLY methods which relate to button
clicking, and reading or displaying variables etc. and a single tDatabaseObj
instance (the tDatabaseObj instance is the one that has does all the work:
it is a good principle to keep data display and input (client) well separate
from the business logic (whether it be local or server));
The whole approach is a bit long winded to start off, but it is very modular
and scalable, and once it is going it, is easier to cope with a project that
sooner or later might get large: I would try to do everything in the
"backend" without third party components (native code is much easier to
update or recompile with later versions), using visual components only in
the GUI modules (you can then easily make multiple versions of these, or
update them);
Hope my personal opinions on the subject are of interest,
Kevin
_______________________________________________
Delphi mailing list -> [email protected]
http://www.elists.org/mailman/listinfo/delphi