BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

refering to objects in a TList--must be a better way

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design
View previous topic :: View next topic  
Author Message
Bill N
Guest





PostPosted: Thu Nov 06, 2003 4:31 pm    Post subject: refering to objects in a TList--must be a better way Reply with quote



I have created three classes (simplified fictious classes): TArticles,
TTitle,TSubTitle

TArticles=class
private
FName: string;
FTitles: TList;
procedure SetTitle(const Value: string);
public
constructor Create;
destructor Destroy;
property Name:string read FName write SetName;
property Titles:TList read FTitles;
end;

TTitle=class
private
FTitle: string;
FSubs: TList;
procedure SetTitle(const Value: string);
public
constructor Create;
destructor Destroy;
property Title:string read FTitle write SetTitle;
property Subs:TList read FDivSubs;
end;

TSubTitle=class
private
FSubTitle: string;
FText: TStrings;
procedure SetSubTitle(const Value: string);
public
constructor Create;
destructor Destroy;
property Title:string read FTitle write SetTitle;
property Text:TStrings read FText Write SetText;
end;

The problem is if I create a TArticles object and try to refer to the
Text property I'm writing code like this:
======================================================================
var sl : TStringList;
Articles : TArticles;
begin
Articles:=TArticles.Create;
sl:=TStringList.Create;
sl.AddStrings(TSubTitle(TTitle(Title.Items[0]).Subs.Items[0]).Text);
end;
======================================================================

There's gotta be a better way of doing this?

Any help would be appreciated?

Thanks,
Bill N
Programmer/Systems Analyst
www.2rs.ca





Back to top
Eric Hill
Guest





PostPosted: Thu Nov 06, 2003 4:59 pm    Post subject: Re: refering to objects in a TList--must be a better way Reply with quote



Quote:
I have created three classes (simplified fictious classes): TArticles,
TTitle,TSubTitle

Probably the easiest thing to do is to build your three classes as list
types themselves. Look for "type-safe lists" in google. I believe there
are also several on CodeCentral.

Basically, instead of a generic TList property, you build type-safe lists
for each type. Something like:

TArticle = class(TObject)
public
property Title: string read...write...;
property IDNumber: Integer read...write...;
end;

TArticleList = class(TObject)
private
function GetArticle(AIndex: Integer): TArticle;
procedure SetArticle(AIndex: Integer; const Value: TArticle);
public
property Item[AIndex: Integer]: TArticle read GetArticle write
SetArticle; default;
end;

Get the idea?

Eric



Back to top
Nathanial Woolls
Guest





PostPosted: Thu Nov 06, 2003 5:25 pm    Post subject: Re: refering to objects in a TList--must be a better way Reply with quote



Quote:
Basically, instead of a generic TList property, you build type-safe lists
for each type. Something like:

To build on Eric's explanation, below is a full, type-safe list
implementation of your TArticle type. It's pretty easy to design something
to generate this code for you, as the only thing that changes is the type
(TArticle) and the instance name (Article):

interface

uses Classes, contnrs;

type

TArticleList = class(TObject)
private
{ Private declarations }
FList: TObjectList;
function GetCount: Integer;
function GetCapacity: Integer;
procedure SetCapacity(const Value: Integer);
function GetArticle(Index: Integer): TArticle;
procedure SetArticle(Index: Integer; const Value: TArticle);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create; virtual;
destructor Destroy; override;
function Add: TArticle; overload;
procedure Add(const Article: TArticle); overload;
property Capacity: Integer read GetCapacity write SetCapacity;
property Count: Integer read GetCount;
procedure Clear;
procedure Delete(const Index: Integer);
function IndexOf(const Article: TArticle): Integer; overload;
procedure Remove(const Article: TArticle);
property Article[Index: Integer]: TArticle read GetArticle write
SetArticle; default;
published
{ Published declarations }
end;

implementation

uses SysUtils;

{ TArticleList }

procedure TArticleList.Add(const Article: TArticle);
begin
FList.Add(Article);
end;

function TArticleList.Add: TArticle;
begin
Result := TArticle.Create;
FList.Add(Result);
end;

procedure TArticleList.Clear;
begin
FList.Clear;
end;

constructor TArticleList.Create;
begin
FList := TObjectList.Create;
end;

procedure TArticleList.Delete(const Index: Integer);
begin
FList.Delete(Index);
end;

destructor TArticleList.Destroy;
begin
FList.Free;
inherited;
end;

function TArticleList.GetCount: Integer;
begin
Result := FList.Count;
end;

function TArticleList.GetCapacity: Integer;
begin
Result := FList.Capacity;
end;

function TArticleList.GetArticle(Index: Integer): TArticle;
begin
Result := TArticle(FList[Index]);
end;

function TArticleList.IndexOf(const Article: TArticle): Integer;
begin
Result := FList.IndexOf(Article);
end;

procedure TArticleList.Remove(const Article: TArticle);
begin
FList.Remove(Article);
end;

procedure TArticleList.SetCapacity(const Value: Integer);
begin
FList.Capacity := Value;
end;

procedure TArticleList.SetArticle(Index: Integer; const Value: TArticle);
begin
FList[Index] := Value;
end;

end.



Back to top
Shawn Oster
Guest





PostPosted: Tue Nov 11, 2003 6:24 pm    Post subject: Re: refering to objects in a TList--must be a better way Reply with quote

Nathanial,

Did you use a code-generator for this list or is it something you cobbled
together? I'd be interested in what you're using to generate it if it is a
tool. Also I noticed that you have the IndexOf method marked as overload
yet there is no other overloaded version in the class. Is that by design or
did you pull a method out for posting?

Thanks,
Shawn

"Nathanial Woolls" <nwoolls (AT) maine (DOT) rr.com> wrote

Quote:
Basically, instead of a generic TList property, you build type-safe
lists
for each type. Something like:

To build on Eric's explanation, below is a full, type-safe list
implementation of your TArticle type. It's pretty easy to design
something
to generate this code for you, as the only thing that changes is the type
(TArticle) and the instance name (Article):

snip/




Back to top
David
Guest





PostPosted: Wed Nov 19, 2003 2:30 am    Post subject: question about function and procedure Add... Reply with quote

Quote:

procedure TArticleList.Add(const Article: TArticle);
begin
FList.Add(Article);
end;

function TArticleList.Add: TArticle;
begin
Result := TArticle.Create;
FList.Add(Result);
end;

Sorry, I can't see the purpose of the function .add. Clues for me?


Also, when loading the list from a database I create a variable of type
TArticle and then use the procedure Add. Is this the 'right' way to do
this?

Thanks
David



Back to top
Jim Cooper
Guest





PostPosted: Wed Nov 19, 2003 9:51 am    Post subject: Re: question about function and procedure Add... Reply with quote


Quote:
Sorry, I can't see the purpose of the function .add. Clues for me?

It just saves you the extra step of creating the new object that was
added. TCollection works like that, for instance.

Quote:
Is this the 'right' way to do this?

It's matter of taste. It saves a line of code to use the function,
that's all. Use the way that seems most sensible to you (and whoever
else is working on the code).

Cheers,
Jim Cooper

____________________________________________

Jim Cooper [email]jcooper (AT) tabdee (DOT) ltd.uk[/email]
Tabdee Ltd http://www.tabdee.ltd.uk

TurboSync - Connecting Delphi with your Palm
____________________________________________

Back to top
David
Guest





PostPosted: Thu Nov 20, 2003 12:52 am    Post subject: 2 more questions about this example Reply with quote

Hi
I am using Nathanial's code, replacing Article with Product, so I have
TProduct and TProductList.

1) However, the following code produces rproduct.cpcode = '',
rproduct.prodname = '' and rproduct = '' at the point indicated.
This is just a sample, I need to load selected records from our 'product'
table into the list (<20).
cbproduct is a TComboBox.

2) in tproductlist.destroy we have flist.free; This line always produces an
application exception. Any ideas?

// in the formshow
rproductlist := tproductlist.create;
rproduct := tproduct.create;
try
rproduct.cpcode := 'Dave';
rproduct.prodname := 'Dave';
rproduct.odbc_name := 'Dave';
rproductlist.add(rproduct);
rproduct.clear_one; // blanks all the fields.

indx := 0;
imax := rproductlist.Count;
while indx < imax do
begin
rproduct := rproductlist.product[indx]; // after running this line
..cpcode, .prodname and .odbc_name are ''
cbproduct.items.add(rproduct.prodname);
inc(indx);
end;
finally
rproduct.free;
end;

// rproductlist.free is in the .onclose

Note: In the past I would have used a string grid for this, quite
successfully. However, Nathaniel's solution is much more flexible so I
would like to understand what I did wrong?

Many thanks
David


Back to top
Harley Pebley
Guest





PostPosted: Thu Nov 20, 2003 1:06 am    Post subject: Re: 2 more questions about this example Reply with quote

Quote:
1) However, the following code produces rproduct.cpcode = '',
rproduct.prodname = '' and rproduct = '' at the point indicated.

// in the formshow
rproductlist := tproductlist.create;
rproduct := tproduct.create;
try
rproduct.cpcode := 'Dave';
rproduct.prodname := 'Dave';
rproduct.odbc_name := 'Dave';
rproductlist.add(rproduct);
rproduct.clear_one; // blanks all the fields.

indx := 0;
imax := rproductlist.Count;
while indx < imax do
begin
rproduct := rproductlist.product[indx]; // after running this line
.cpcode, .prodname and .odbc_name are ''
cbproduct.items.add(rproduct.prodname);
inc(indx);
end;
finally
rproduct.free;
end;

// rproductlist.free is in the .onclose

You are creating a list and an object. Then you are putting data in the
object and adding that object to the list. Then you are clearing the
object. It's working as written. Remember, the object in the list is the
same as the local reference. You have two references to the same object,
not two different objects. What happens in one will show up when accessed
via the other reference.

Quote:
2) in tproductlist.destroy we have flist.free; This line always produces an
application exception. Any ideas?

I expect you meant rproductlist.free. Is the list an TObjectList
descendent? If so, OwnsObjects is defaults to true and it is trying to free
the objects in the list, but you've already freed it above. The AV is on
the second free call. This condition is known as a "stale pointer". You end
up with a reference to an object that doesn't exist.

HTH,
Harley Pebley

Back to top
David
Guest





PostPosted: Thu Nov 20, 2003 2:38 am    Post subject: Thanks Reply with quote

While I was a by-stander in this discussion, with some of my own questions,
I learnt a lot here.
A big thanks to everyone involved. Much appreciated.
David


Back to top
Joanna Carter (TeamB)
Guest





PostPosted: Thu Nov 20, 2003 7:57 am    Post subject: Re: Thanks Reply with quote

David wrote:

Quote:
While I was a by-stander in this discussion, with some of my own
questions, I learnt a lot here.

Which discussion was that?

Joanna

--
Joanna Carter (TeamB)

Consultant Software Engineer
TeamBUG support for UK-BUG
TeamMM support for ModelMaker



Back to top
David
Guest





PostPosted: Thu Nov 20, 2003 9:01 am    Post subject: Re: Thanks Reply with quote

Quote:

Which discussion was that?

Joanna

The gentlemen in this thread were discussing using TObjectList and proposed
a way by which it could be used (which I understood)
David.



Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> Delphi OO design All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.