Need Nested Object/ArrayList advice

alreadyused

Well-known member
Joined
Jan 13, 2006
Messages
70
I am needing some direction. I am going to describe this as toys because I think that would be the easiest way. Sorry, this is gonna be wordy; better get out your pillow! :-)

I have a large room that holds a lot of large boxes that will eventually hold an indeterminate amount of toys. While these toys are under construction, they have an indeterminate amount of prototypes. So:

ROOM
|
|_BOX1
|___ToyA
| |___ToyA-RevA
| |___ToyA-RevB
| |___ToyA-RevC
|
|___ToyB
|___ToyB-RevA
|___ToyB-RevB
and so on.

My thought is:
Code:
VB.Net 03 Developer
Public Class clsRoom
   Private listBoxes as ArrayList contains Box objects
   Private objBoxes as New clsBox
   Methods and Properties
End Class clsRoom

Public Class clsBox
   Private listToys as ArrayList contains Toy objects
   Private objToy as New clsToy
   Methods and Properties
End Class clsBox

Public Class clsToy
   Private listRevs as ArrayList contains Revision Objects
   Private objRev as New clsRev
   Methods and Properties
End Class clsToy

Public Class clsRev
   Private Var1, Var2, ... as ... Revision variables
   Methods and Properties
End Class clsRev

What Im having a problem with is how to decide if I need to make a new object. For example, how do I look through the array list and determine if that object is in there already?

Then, also, is it going to matter what order I go in? Meaning, do I need to:
create all of the Revisions first,
then Determine if a Toy exists to hold the revisions
then Determine if a Box exists to hod the toy?

Or should I do it the other way around? We will eventually have thousands of boxes holding handfuls of toys each, and each toy having multiple (usually no more than five, but flexible) revisions.


Any ideas/suggestions/comments/"you idiot why are you doing it that way"s are more than welcome!

Thanks!

Damon
 
You used the word prototype and then revision.

To me a prototype is a branch off of the main path but a revision follows the same linear path, which is it?

Does Rev B inherit the properties from Rev A or just from Toy A?

Technically, I would use typed collections..google or search this forum..lots of info.

Design-wise:

Im assuming a revision is a branched path.

How in-depth is this solution going to be?

I would firstly make interfaces for a room, a box and a toy.
You could even make interfaces for the typed collections...ie. IToyCollection, IBoxCollection, IRoomCollection

Then make the base class for a room, which obviously inherits from the room interface, and the same for box and toy.


The room base class contains a type collection of boxes.
Each Box object in the Box Collection contains a type collection of toys.

The revision objects are simply child objects of whatever toy class they are prototypes of.

For instance:

WalkingRobot baseWalkingRobot = new WalkingRobot();
WalkingTalkingRobot walkingRobotRev1 = new WalkingTalkingRobot();

In this case the WalkingTalkingRobot class inherits from WalkingRobot and is considered a prototype.

Using this design, the questions you asked become irrelevant.

Im not going to post any code...because...well, thats the fun part :)
 
Edited reply

Moved all of that text to the attached .txt file

Heres what I have currently;
Job Object (Box), Product Object (Toy), Revision Object (Revision)
Typed Collections of Jobs, Product and Revisions

My room is now a treeview control, and I have Jobs as the primary node; working on adding the others as sub-nodes;

New question, all the jobs have:
strJobSerial
strJobName

All the Products have:
strJobSerial
strProductSerial
strProductName

All the revisions have:
strJobSerial
strProductSerial
strRevisionSerial
strRevisionNotes

The str***Name is simply for the user; but I would like to display that on the tree, so for the primary I did (hiding a bunch of code handling getting the objects, looping, etc.)
.Nodes = obj.JobSerial & "-" & obj.JobName

Now, that creates a problem with adding the sub-nodes unless I persist all of that information through all of the objects.

I guess by that statement you have figured out that I have the Job, Product and Revision objects as independent objects, i.e. no inheritence. I have only used that in Java, and its been 2 years, so I was skipping it.

Am I being too lazy, should I be doing inheritance? Im sure I know the answer to that is YES!!!! But I thought Id check anyway.

Thanks again!

Damon
 

Attachments

Last edited by a moderator:
inheritence decision

Well, for the time being I have decided not to use inheritance. Although the objects do have some of the same properties, all I am using them for is storing and retrieving data, meaning all properties, no methods (other than the constructor).

Furthermore, since one Job holds multiple Products and Revisions, if I create a new job object every time I make a new Product or new Revision, I will have way too many job objects... at least thats my understanding of it.

So, again, if anyone has any input please feel free to post! Im just hacking my way through this without a real clue! :p
 
Ok, I was bored so I decided to look at how I might achieve what you are attempting. Heres what I came up with, I hope I got the right idea. I would basically use the structure below but using Typed Arrays to prevent casting on the Product, and Revision collections.

C#:
using System;
using System.Collections;

namespace Toys
{
	public class Job 
	{
		private ArrayList myProducts;
		private string _name, _serial;

		public ArrayList Products 
		{
			get { return myProducts; }
		}

		public string Serial 
		{
			get { return _serial; }
			set { _serial = value; }
		}

		public string Name 
		{
			get { return _name; }
			set { _name = value; }
		}

		public Job(string name, string serial) 
		{
			myProducts = new ArrayList();
			_name = name;
			_serial = serial;
		}

		public void AddProduct(string name, string serial)
		{
			Product tmpProduct = new Product(name, serial, this);
			myProducts.Add(tmpProduct);
		}
	}

	public class Product 
	{
		private ArrayList myRevisions;
		private Job _parent;
		private string _name, _serial;
		
		public ArrayList Revisions
		{
			get { return myRevisions; }
		}
		public Job Parent 
		{
			get { return _parent; }
			set { _parent = value; }
		}

		public string Serial 
		{
			get { return _serial; }
			set { _serial = value; }
		}

		public string Name 
		{
			get { return _name; }
			set { _name = value; }
		}

		public Product(string name, string serial, Job parent)
		{
			myRevisions = new ArrayList();
			_name = name;
			_serial = serial;
			_parent = parent;
		}

		public void AddRevision(string notes, string serial)
		{
			Revision tmpRevision = new Revision(notes, serial, this);
			myRevisions.Add(tmpRevision);
		}
	}

	public class Revision 
	{
		private Product _parent;
		private string _notes, _serial;

		public Product Parent 
		{
			get { return _parent; }
			set { _parent = value; }
		}

		public string Serial 
		{
			get { return _serial; }
			set { _serial = value; }
		}

		public string Notes 
		{
			get { return _notes; }
			set { _notes = value; }
		}

		public Revision(string notes, string serial, Product parent) 
		{
			_notes = notes;
			_serial = serial;
			_parent = parent;
		}
	}
}

Its pretty similar to the first example you gave only I store the parent of an object so that for example a revision knows what its products serial is etc.
 
my version

Cags said:
...I would basically use the structure below but using Typed Arrays to prevent casting on the Product, and Revision collections....
Its pretty similar to the first example you gave only I store the parent of an object so that for example a revision knows what its products serial is etc.

Thanks for the reply!

Just a quick question on yours (and inheritance in general), assume that I have one job that has 5 products which have 5 revisions; I would end up with 25 job objects, correct?

This is a program to replace an existing DOS based one; I dont see us going back and entering old data, however we have somewhere around 10,000 jobs, each with at least one product, many with multiples, and then of course, theres the revisions.

I will be archiving a lot of that though, and will try to keep the list of jobs to under 500 active at a time...

So:
1. is my understanding of the SUPERS job correct?
2. do I need to worry? :eek:

FYI, heres what Im currently doing (collapsed view on most)...

Code:
object containers - only showing clsRev b/c clsJob and clsProduct are this w/ less vars and properties

Friend Class clsRev
    Rev object (objRev) will be stored in Rev Collection (objRevColl)

    Revision values
    Private _strRevNotes As String
    Private _datRevDate As DateTime
    Private _dblOutLength As Double
    Private _dblOutWidth As Double
    Private _dblOutHeight As Double
    Private _bolActive As Boolean

    identifiers
    Private _strRevSerial As String
    Private _strJobSerial, _strProductSerial As String
    Private _intIndexJob, _intIndexProduct, _intIndexRev As Integer

    Friend Sub New(ByVal strJobSerial As String, ByVal strProductSerial As String, ByVal strRevSerial As String, ByVal strRevNotes As String, ByVal datRevDate As DateTime, ByVal bytActive As SByte)
        _strJobSerial = strJobSerial
        _strProductSerial = strProductSerial
        _strRevSerial = strRevSerial
        _strRevNotes = strRevNotes
        _datRevDate = datRevDate
        _bolActive = bytActive.ToString
    End Sub

    Friend Property IndexJob() As Integer
        Get
        Set(ByVal Value As Integer)
    End Property
    Friend Property IndexProduct() As Integer
        Get
        Set(ByVal Value As Integer)
    End Property
    Friend Property IndexRev() As Integer
        Get
        Set(ByVal Value As Integer)
    End Property
    Friend ReadOnly Property JobSerial() As String
    Friend ReadOnly Property ProductSerial() As String
    Friend ReadOnly Property RevSerial() As String
    Friend ReadOnly Property RevDate() As DateTime
    Friend ReadOnly Property RevNotes() As String
    Friend ReadOnly Property Active() As Boolean
    Friend ReadOnly Property OutLength() As Double
    Friend ReadOnly Property OutWidth() As Double
    Friend ReadOnly Property OutHeight() As Double
End Class clsRev

Typed Collections - only showing one because the others are pretty similar
Public Class clsProductColl
    Inherits CollectionBase

    Friend Function Add(ByVal objProduct As clsProduct) As Integer
        Dim intI As Integer
        Dim bolExists As Boolean = False
        Dim objTemp As clsProduct

        handler to prevent duplicate addition
        If InnerList.Count <> 0 Then
            For intI = 0 To InnerList.Count - 1
                objTemp = Innerlist.Item(intI)
                If objTemp.JobSerial = objProduct.JobSerial And objTemp.ProductSerial = objProduct.ProductSerial Then
                    bolExists = True
                    Exit For
                End If objTemp = objProduct
            Next intI
        End If InnerList.Count

        objTemp = Nothing
        If bolExists = False Then
            Return InnerList.Add(objProduct)
            Else
                Return InnerList.Clone
        End If bolExists
    End Function Add

    Friend Function Remove(ByVal objProduct As clsProduct)
    Friend Function RemoveRange(ByVal intIndex As Integer, ByVal count As Integer)
    Default Friend Property Item(ByVal intIndex As Integer) As clsProduct
End Class clsRevColl

Then I have code elsewhere that creates the objects, adds them to the collections, then takes info from the collections and makes the tree.
 
Last edited by a moderator:
Well one of us is certainly confusing something.
alreadyused said:
Just a quick question on yours (and inheritance in general), assume that I have one job that has 5 products which have 5 revisions; I would end up with 25 job objects, correct?

The code I posted doesnt actually use any inheritance. Its simply a hierarchical structure of collections. If you had one job with 5 products each having 5 revisions you would have 31 objects (consisting of 1 job object, 5 product objects, and 25 revision objects). There would only be a single job object which contains a collection of product objects, each of which will contain a collection of revision objects.

You can think of it as a family tree, Imagine you have 5 children, each of which has 5 children. Theres still only one of you but you now have 5 children and 25 grandchildren, giving a total of 31 people.
 
Sorry, I guess thats why I should have STUDIED the code before replying instead of just skimming it! :rolleyes:

I just assumed it was inheritance, but I see now that youre creating the object variable inside the child and setting it to the parent; so I see the tree thing working.

Looks really simple when you do it! LOL. Thanks for the input and advice, I really appreciate it. That looks quite a bit cleaner than my version; mines working right now, but Im also ahead of schedule so I may clean it up.
 
Finished!!! (Almost)

Ok, first, thank you Diesel and Cags for your comments, ideas and suggestions, I really appreciate it!

I started cleaning everything up yesterday and got this trimmed down quite a bit; I am not currently using inheritence, but as you will see with the methods, I probably should be. I am using generic object references so that I can reuse this when I finally get around to it. Thats my final step I think, but I may just leave it as is for now and move on. Guess thats laziness huh? :p

I liked Cags idea of storing the child objects in their parents objects, so I am doing that; previously I had a separate collection object for each object, not really sure why I did that, but it worked... (to be continued)
 
part2

JobList holds jobs which hold units which hold revisions. Except for revisions, everything is pretty basic; revisions have a few more properties. I currently have (as close as I can come to UML):
[VB]
+clsJobList
-_arrayL : ArrayList stores child objects
#Count(): Integer returns number of objects in _arrayL
+Add (strSerial :String, strName :String) :Void invokes child "New" method
#Child (strSerial :String) :Object child object found by "serial"
#Child (intIndex :Integer) :Object child object found by index
#Index (strSerial :String) :Integer index position of objJob (by "serial")
[/VB][VB]
+clsJob
-_arrayL : ArrayList stores child objects
-_intIndex :Integer childs position in _arrayL
-_strSerial :String objs serial#
-_strName :String objs name
#Count(): Integer returns number of objects in _arrayL
+New (strSerial :String, strName :String) :Void
+Add (strSerial :String, strName :String) :Object invokes child "New" method and returns child
#Child (strSerial :String) :Object child object found by "serial"
#Child (intIndex :Integer) :Object child object found by index
#Serial() :String serial of object
#Name() :String name of object
#Index (strSerial :String) :Integer index position of child by "serial"
[/VB]
 
part3

[VB]
+clsUnit
-_arrayL : ArrayList stores child objects
-_intIndex :Integer childs position in _arrayL
-_strSerial :String objs serial#
-_strName :String objs name
#Count(): Integer returns number of objects in _arrayL
+New (strSerial :String, strName :String) :Void
+Add (strSerial :String, strName :String) :Object invokes child "New" method and returns child
#Child (strSerial :String) :Object child object found by "serial"
#Child (intIndex :Integer) :Object child object found by index
#Serial() :String serial of object
#Name() :String name of object
#Index (strSerial :String) :Integer index position of child by "serial"
[/VB]
 
well its not liking my RevClass so I have to put that in a text file; that should be here...

Now, for object creation/handling, instead of tracking parents, I am tracking children. I am able to loop in the following order:
[VB]
Loop 1
For intI = 0 to rsJobs.RecordCount -1
objJL.Add(args)Add jobs to joblist
If Not rsJob.BOF Then rsJob.MovePrevious()listing in reverse order​
Next intI

Loop 2
For intI = 0 to objJL.Count -1
objJob = objJL.Child(rsRev args)Get a Job! LOL :-) Based on Serial pulled from DB
objUnit = objJob.Add(args) Add objUnit to objJob, returns clsUnit; dupe detector in Add method
objRev = objUnit.Add(args) Add objRev to objUnit, returns clsRev
If Not rsRev.EOF Then rsRev.MoveNext()
Next intI
[/VB]

So thats pretty much it; that cut out somewhere around 250 lines of code and 4 classes by doing it this way; inheritence should help more too if I do that. Thanks again!

Damon
 

Attachments

So heres the final w/ inheritance

So heres the final version (txt file) using inheritance; cleaned it up quite a bit. Thanks again to all for the tips, help, suggestions, examples, etc.

Damon
 

Attachments

Back
Top