Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Creating / naming multiple class instances in code at run-time 2

Status
Not open for further replies.

CraigBest

Programmer
Aug 1, 2001
545
US
Hi Folks

I am writing an app in which I have a varaible number of instances of a class I need to instantiate. I have no problem creating a single instance by declaring a literal value as a new instance of the class. But what I want to do is create a for next loop that creates as many instances of the class as I need.

I have it in mind to do something like this:

Dim sObjNum As String
For Each drTrack In dtTrack.Rows
'create a new Track Object
sObjNum = "Tk" & Format(TkIncr, "00")
Public (sObjNum) As clsTrack
sObjNum.BlockID = drTrack.Item("BlockID").ToString()
...
TkIncr += 1
Next

...But as you can imagine VB does not like the variable in place of a literal value when naming the instance.

I know I'm going about this the wrong way, but I don't know what the right way is. Do I need to give each insrance a unique name? Can I just create them all with the same name (the properties will be different in each, with a unique set of values).

Can someone steer me in the right direction?

Thanks


CraigHartz
 
Create an unbounded array of the object type, and size the array for the number of objects you need.

Dim ObjArray(dtTrack.Rows.Count - 1) As clsTrack

For r As Integer = 0 to dtTrack.Rows.Count - 1
ObjArray(r) = New clsTrack
ObjArray(r).BlockID = dtTrack.Rows(r).Item("BlockID").ToString()
Next

I used to rock and roll every night and party every day. Then it was every other day. Now I'm lucky if I can find 30 minutes a week in which to get funky. - Homer Simpson

Arrrr, mateys! Ye needs ta be preparin' yerselves fer Talk Like a Pirate Day!
 
Oops, I meant to say "Create an array...", not "Create an unbounded array...". Sorry about that.


I used to rock and roll every night and party every day. Then it was every other day. Now I'm lucky if I can find 30 minutes a week in which to get funky. - Homer Simpson

Arrrr, mateys! Ye needs ta be preparin' yerselves fer Talk Like a Pirate Day!
 
What you need to do really depends on what you want to do with the instances after you have created them.

1) What is a Track Object? Is it a type of form, control, etc?
2) What happens to them after all of them are created?

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
Sorwen,

Good question. The app is designed to keep track of trains as they move along on a railroad. The railroad is made of of blocks, or sections, from one end to the other and each block may have one or more tracks in it. More than one track in a block usually represents a place where trains can pass each other. A track object represents a section of railroad track.

So the way I'm planning this is to create all these objects as instances of a class. There will be instances of blocks, and instances of Tracks (which will inherit some attributes from the Blocks they belong to). The track instances will have other properties that can be set at run-time, including whether or not the track is occupied, by what train, and which trains may have the right to occupy that track (not the same thing).

All the instances are loaded from a database file, each instance representing a row from the table that represents it.

This is the first time I'm trying to build an application using classes like this, and frankly I'm not sure about what I'm doing or if this will even work. But I'm trying to grow my sills a bit and this seemed like a good way to learn.

That help?

CraigHartz
 
:) Jebenson posted while I was deciding how to handle your question. You can handle them as an object array or a collection.

The only reason I asked was for instance lets say that each track object was a control (a button for instance) then generally you don't need to bother with an array or collection and you can just keep reusing the same variable. Once the object is added to the form it doesn't matter what you called it when you created it.
Code:
    For Each drTrack In dtTrack.Rows
        'create a new Track Object
        Public CurrentTrack As New clsTrack
        CurrentTrack.Name = "Tk" & Format(TkIncr, "00")
        CurrentTrack.BlockID = drTrack.Item("BlockID").ToString()
        ...
        Me.Controls.Add(CurrentTrack)
        TkIncr += 1
    Next
Same thing if it is a form that is shown and doesn't need to be referenced buy the created from again. But Object Arrays and Collections are great though if you want to deal with those same sets of objects later.

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
Sorwen,

Thanks for the post. I can see where that would be really useful for a set of controls.

I like the array approach (working well so far BTW) but I had been interested in creating a collection of these instances, just hadn't gotten there yet - don't suppose you could show me an example of how to do that as opposed to the Array, could you?

Thanks very much

CraigHartz
 
Same code as a Collection
Code:
    Dim TrackCollection As New Collection
    For Each drTrack In dtTrack.Rows
        'create a new Track Object
        Public CurrentTrack As New clsTrack
        CurrentTrack.Name = "Tk" & Format(TkIncr, "00")
        CurrentTrack.BlockID = drTrack.Item("BlockID").ToString()
        ...
        TrackCollection.Add(CurrentTrack)
        TkIncr += 1
    NextNext

Or even better sometimes you could do a ListOf
Code:
    Dim TrackCollection As New List(Of clsTrack)
    For Each drTrack In dtTrack.Rows
        'create a new Track Object
        Public CurrentTrack As New clsTrack
        CurrentTrack.Name = "Tk" & Format(TkIncr, "00")
        CurrentTrack.BlockID = drTrack.Item("BlockID").ToString()
        ...
        TrackCollection.Add(CurrentTrack)
        TkIncr += 1
    NextNext

But really if all is well there isn't much reason to bother changing in this instance. A collection is just great if you don't already know the total number of objects or if you are going to keep changing it's size by adding/removing objects.

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
That's great, thanks. There are other groups of instances that may be variable in number (such as the Train class which I have not coded yet). So that might work out really well.

One more question if I might: Looking down the road, I know I'm going to have to find specific objects in the array / collection at some point - for instance, say I am tracking a train from one block to the next. Current block has blockID of 50, and the next blockID I want is 60 - what is the best way of getting the element or instance I'm looking for? I know I can set up a loop to go through the array or collection looking for the BlockID value and stop when I hit it, but is there some way of finding the desired object via random access rather than an iterative search?

Thanks again

CraigHartz
 
If you use a Collection you can set a Key (does not work on a ListOf). Then you can say return the item that contains that Key. For example:

Code:
    Dim TrackCollection As New Collection
    For Each drTrack In dtTrack.Rows
        'create a new Track Object
        Public CurrentTrack As New clsTrack
        CurrentTrack.Name = "Tk" & Format(TkIncr, "00")
        CurrentTrack.BlockID = drTrack.Item("BlockID").ToString()
        ...
        TrackCollection.Add(CurrentTrack[Red], CurrentTrack.Name[/Red])
        TkIncr += 1
    NextNext

All that did was add a Key. The key has to be unique so I used the the name you wanted to set since the way you did it that should be unique.

Then when you want to call back say TK100 you would do something like.
Code:
Dim GetTrackObject As clsTrack = TrackCollection.Item("TK100")

Actually it would really be best to make sure the TrackObject exists first:
Code:
Dim GetTrackObject As clsTrack
If TrackCollection.Contains("TK100") Then
    GetTrackObject = TrackCollection.Item("TK100")
End If

Hope that answers. I've been frying my brain on my current project so something could be missing.

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
Sorwen - Thanks so much for your insight! This is very helpful. I really appreciate your taking the time to answer these questions.

Best of luck on the project!

CraigHartz
 
NP. Same to you.

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
Hey there Sorwen,

One more question about one of the code examples you provided. I wrote the following code based on what you gave me:

Code:
    Private Sub LoadTracks()
        'define the Tracks that make up the blocks.
        Dim drTrack As DataRow
        Me.TrackTableAdapter.Fill(Me.DsSpatcher.Track)

        For Each drTrack In DsSpatcher.Track.Rows
            Dim CurrentTrack As New clsTrack
            CurrentTrack.BlockID = drTrack.Item("BlockID").ToString
            'Get the block data associated with the track 
            Dim GetBlockObj As clsBlock
            If BlockCollection.Contains(CurrentTrack.BlockID) Then
                GetBlockObj = BlockCollection.Item(CurrentTrack.BlockID)
                CurrentTrack.BlockName = GetBlockObj.BlockName
                CurrentTrack.BlockEast = GetBlockObj.BlockEast
                CurrentTrack.BlockWest = GetBlockObj.BlockWest
...
Next

Problem is that the If BlockCollection.Contains statement returns the name of the collections ojject as it should - but I think what I really need here is the index in order to read the values of the collection object. I get an error on the next statement saying the index is out of bounds, true considering "20" is the name of the object but it's index value is 1.

What do I need to change in the line GetBlockObj = BlockCollection.Item(CurrentTrack.BlockID)?

Thanks




CraigHartz
 
Look at Sorwen's earlier post again, specifically this line:

TrackCollection.Add(CurrentTrack, CurrentTrack.Name)

Note the second parameter in the Add method. This will be the key you use to look up specific elements in the collection, and this key must be unique. If CurrentTrack.BlockID is unique for each object in the collection, you can do the add like this:

TrackCollection.Add(CurrentTrack, CurrentTrack.BlockID.ToString())

Then you would get a specific item in the collection like so:

If BlockCollection.Contains(CurrentTrack.BlockID.ToString()) Then
GetBlockObj = BlockCollection.Item(CurrentTrack.BlockID.ToString())



I used to rock and roll every night and party every day. Then it was every other day. Now I'm lucky if I can find 30 minutes a week in which to get funky. - Homer Simpson

Arrrr, mateys! Ye needs ta be preparin' yerselves fer Talk Like a Pirate Day!
 
JE,

Thanks. I don't understand why adding the .ToString made a difference, but it worked.

CraigHartz
 
Because CurrentTrack.BlockID can be 1000 (Integer) which is a possible index, but CurrentTrack.BlockID.ToString is "1000" (String) which can only be a possible Key. The only way it knows to look for it as a Key is because it is a string.

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
Ah, I did not understand that the Key had to be in the form of a string. Makes sense, then. You were right, originally the value I gave you (which you used as the key) was a string, I changed it to a different field with a numeric value. I suppose if I had left things as they were the .ToString modifier would not have been necessary.

Well you learn something new every day (and several things today) - thank you both!

CraigHartz
 
They say it is always a good day when you learn something new. I just wish I could quit forgetting what I learned the next day. :)

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top