previous chapter contents page top page next chapter

ObjectList

June 10, 1992last updated April 1, 1994

Defined in List.Def 
Inherits from FixedList, HasIndexing

Class Description

An object list is an ordered collection of data elements, each of which is a 4-byte object ID denoting a member of class Object. Class ObjectList defines the generic behavior of such lists and provides the foundation for a large family of more specialized list classes, as shown in the hierarchy above.

Using an ObjectList Object

If your program needs to use an object list, you can create one by specifying it in your object definition file. Often, however, instead of creating a direct instance of class ObjectList, you'll want to use one of its many system-defined subclasses: for example, class TaskList represents a chronologically sorted list of "to-do" tasks for the datebook, and ObjectStack is a list of arbitrary objects accessed in last-in-first-out order. If none of the built-in subclasses is appropriate for your purposes, you can define a subclass of your own.

Programming Information

Instantiate: sometimes
Subclass: sometimes
Call its methods: sometimes

Like all lists, an object list keeps its elements arranged in a definite sequential order. Each list element can be accessed by its index, which is an integer value indicating the element's location within the list. The index numbering is one-based: that is, the first element in the list is number one, which is the way most humans think. The list also remembers the index of its current element, the last one accessed or returned by a method call.

The distinguishing characteristic of an object list is that all of its elements are object IDs denoting members of the various subclasses of class Object. The objects in the list need not all belong to the same class. For example, the window that appears when you tinker with an object on the screen includes switches, meters, text field objects, other lists, and more; all of these diverse objects are elements of a single object list.

Here's an example of a tinker window object list:

Instance ObjectList 'Tinker' 20;
         length: 35;
          entry: (TinkerWindow 317);
          entry: (ImageCoupon 388);
          entry: (Switch 'can move' 319);
          entry: (Switch 'can stretch' 320);
          entry: (SoundCoupon 364);
          entry: (Meter 'bytes' 322);
          entry: (Switch 'show label' 323);
          entry: (Switch 'frame label' 324);
          entry: (LabelChooser 'Label' 325);
          entry: (BorderCoupon 326);
          entry: (Switch 'editable' 327);
          entry: (Switch 'second hand' 387);
          entry: (Switch 'select all' 383);
          entry: (Switch 'wide margins' 329);
          entry: (ShapeCoupon 330);
          entry: (Meter 'horizontal speed' 331);
          entry: (Meter 'vertical speed' 332);
          entry: (Meter 'frame delay' 333);

          entry: (Switch 'moving' 334);
          entry: (Switch 'hBounce' 335);
          entry: (Switch 'vBounce' 336);
          entry: (Switch 'hFlip OK' 337);
          entry: (Switch 'vFlip OK' 338);
          entry: (Switch 'turn right' 339);
          entry: (Switch 'turn left' 340);
          entry: (Switch 'rotate OK' 341);
          entry: (Meter 'max lines' 342);
          entry: (Switch 'can touch' 356);
          entry: (Switch 'can copy' 358);
          entry: nilObject;
          entry: (LineStyleCoupon 360);
          entry: (ShadowCoupon 361);
          entry: (ScriptCoupon 369);
          entry: (TextStyleCoupon 'Font' 370);
          entry: (Switch 'editable' 347);
End Instance;

If you wish, you can subclass ObjectList to create a more specialized list of objects. For example, the TaskList class in the datebook package mixes in class SortedList to create a sorted list of objects, and also adds methods to work with dates.

Methods you might call

Class ObjectList has the following methods that you might Call:

Method Description
Initialization
Initialize Initialize fields
List structure
Reverse Reverse order of elements
Element access
At Get object at a given index
Adding and removing elements
AddTo Add an object to list
AddAt Add an object at a given index
AddUnique Add an object if it isn't already in list
AddFirst Add an object at beginning of list
AddLast Add an object at end of list
InstallInto Install an object in list
Remove Remove an object from list
ReplaceAt Replace object at a given index
AppendList Add items from another list to this list
AppendListUnique Add items from another list only if they aren't already in this list
Searching
Search Search list for a given object
FindAfter Search for an object, beginning at a given index
FindElemAfter Search for an element, beginning at a given index
FindEqualIndexical Call FindEqual on an indexical list and return an indexical for the match
String matching
FindByName Search for an object with a specified name
FindClosestMatch Search for object name most nearly matching a string, beginning at a given index
Low-level object management
GetEachField Apply a function to each field and each object in list
EachReference Apply a function to each object reference in list or its fields
Unload Prepare to unload list's cluster
EachExtraField Apply a function to the extra fields of each list item
MakeValid Replace invalid list elements with nil objects
InstallInto
MakeChoiceList
DestroyContents Destroy each list element and empty the list
FileTo

Methods you might override

You might want to override these other methods under the following circumstances:

Method When to override
class ObjectList If you need to process a new list

Description of fields

Class ObjectList doesn't define any fields of its own, but inherits just one field from its superclasses:

Field Type Description
Inherited from AbstractList:
length Unsigned Number of elements in list

Every object list has extra fields that contain the list's items. The extra fields are often named entry.

Method Descriptions

Initialization

Initialize

overrides Initialize

Call: rarely
Override: sometimes

When a new object list is created, the system calls Initialize to allow the new list to set itself up. ObjectList_Initialize creates a stack containing the initial list entries. It pops each entry from the stack and calls AddFirst to add the new entry to the list.

You should override Initialize if your list subclass requires any additional processing when a new list is created. Be aware, though, that the system calls Initialize only when constructing a list created with a New call. If you want initialization performed on a list created in an Objects.Def file, you should subclass ObjectList and inherit from the HasLoad mixin. Put your initialization code into Load.

List Structure

Reverse

operation Reverse(); noFail

Call: sometimes
Override: rarely

Call Reverse to rearrange an object list's elements in reverse order. The first element of the list becomes the last, the second element becomes the next-to-last, and so on, and the last element becomes the first.

Element Access

At

operation At (index: Unsigned): Object; noFail

Call: sometimes
Override: rarely

Call At to get the object at a given index position in an object list. The index parameter designates the position of the desired object within the list. If index is less than one or greater than the length of the list, the result is nilObject. (Notice that nilObject can also be a legitimate element of the list. If you need to distinguish between a nil list element and an out-of-range index, you must range-check the index yourself.)

For example, suppose that an object list named testList contains the following objects:

Index Element
1 objectA
2 objectB
3 objectC
4 objectD

Here are some sample calls:

theObject  = At(testList,  2);/* Returns objectB */
someObject = At(testList, 10);/* Returns nilObject */
anObject   = At(testList,  1);/* Returns objectA */

In each case, At returns to you the result of a MakeUseable call on the object.

Adding and Removing Elements

AddTo

operation AddTo (newElement: Object); noFail

Call: sometimes
Override: rarely

Call AddTo to add an object to an object list. newElement is the object to be added; it is placed at the end of the list, following the last existing object. AddTo accomplishes this worthy goal by simply calling MakeStorable and then AddElem on the lucky new item.

For example, suppose you have an object list named testList, containing the following objects

Index Element
1 objectA
2 objectB
3 objectC

If you make this call

AddTo (testList, objectX);

testList will look like this:

Index Element
1 objectA
2 objectB
3 objectC
4 objectX

AddAt

operation AddAt (index: Unsigned; newElement: Object)

Call: sometimes
Override: rarely

Call AddAt to add an object to an object list at a given index position. newElement is the object to be added; it is inserted in the list at the position indicated by index. If index is less than one or greater than the length of the list plus one, the operation fails with the exception cannotFindIndex.

The object previously at the specified index position and all objects following it in the list are moved back one position. If necessary, the list is enlarged to make room for the new object. AddAt does its work by calling MakeStorable to get a storable version of the object, then calling AddElemAt on the result.

For example, suppose you have an object list named testList containing the following objects

Index Element
1 objectA
2 objectB
3 objectC

If you make this call

AddAt (testList, objectX, 2);

testList will look like this:

Index Element
1 objectA
2 objectX
3 objectB
4 objectC

AddUnique

operation AddUnique (newElement: Object)

Call: sometimes
Override: rarely

Call AddUnique to add an object to an object list if it is not already there. newElement is the object to be added; if the list does not already contain this object, it is added at the end of the list, following the last existing object. If the specified object is already in the list, AddUnique has no effect. AddUnique calls MakeStorable on the object, and then AddUniqueElem. See the section on AbstractList_AddUniqueElem for more information.

For example, suppose that an object list named testList contains the following objects:

Index Element
1 objectA
2 objectB
3 objectC
4 objectD

Here are some sample calls:

AddUnique (testList, objectA); /* Doesn't change the list */
AddUnique (testList, objectZ); /*Adds objectZ at end of list */
AddUnique (testList, objectB); /* Doesn't change the list */

AddFirst

operation AddFirst (newElement: Object), safe;

Call: sometimes
Override: rarely

Call AddFirst to add an object to the beginning of an object list. newElement is the object to be added; it is placed before the first existing object in the list. All existing objects are moved back one position. AddFirst does its work by calling MakeStorable and then calling its inherited method AbstractList_AddElemFirst.

For example, suppose you have an object list named testList containing the following objects

Index Element
1 objectA
2 objectB
3 objectC

If you make this call

AddFirst (testList, objectX)

testList will look like this:

Index Element
1 objectX
2 objectA
3 objectB
4 objectC

AddLast

operation AddLast (newElement: Object)

Call: sometimes
Override: rarely

Call AddLast to add an object to the end of an object list. newElement is the object to be added; it is placed after the last existing object in the list. AddLast does its work by calling MakeStorable and then calling its inherited method AbstractList_AddElemLast.

For example, suppose you have an object list named testList containing the following objects

Index Element
1 objectA
2 objectB
3 objectC

If you make this call

AddLast (testList, objectX)

testList will look like this:

Index Element
1 objectA
2 objectB
3 objectC
4 objectX

Remove

operation Remove (theElement: Object), noFail

Call: sometimes
Override: rarely

Call Remove to remove an object from an object list. theElement is the object to be removed; the first occurrence of this object is removed from the list. Remove does its work by calling MakeStorable and then calling its inherited method AbstractList_RemoveElem. If the list does not contain the specified object, the operation fails with the exception cannotFindElement. See the section on AbstractList_RemoveElem for more information.

All objects following the one being removed are moved forward one position in the list. The extra space previously occupied by the last object in the list is not deallocated, but is cleared to zeroes; since the list's element count is reduced by one, this space becomes inaccessible as part of the list. (It may eventually be reclaimed via the Compact method; see the description of FixedList_Compact for more information.)

For example, suppose you have an object list named testList containing the following objects

Index Element
1 objectA
2 objectB
3 objectC
4 objectD

If you make this call

Remove (testList, objectB);

testList will look like this:

Index Element
1 objectA
2 objectC
3 objectD

ReplaceAt

operation ReplaceAt (index: Unsigned; newElement: Object)

Call: sometimes
Override: rarely

Call ReplaceAt to store a new object into an object list at a given index position. newElement is the object to be inserted; this becomes the new list element at the position indicated by index. The previous object at that index, if any, is lost; other objects in the list are not affected.

For example, suppose you have an object list named testList containing the following objects

Index Element
1 objectA
2 objectB
3 objectC
4 objectD

If you make this call

ReplaceAt (testList, 2, objectX);

testList will look like this:

Index Element
1 objectA
2 objectX
3 objectC
4 objectD

If index is less than one, the operation fails with the exception cannotFindIndex. If index is greater than the length of the list, the list is enlarged to include a new object at that index; any intervening objects are initialized to nilObject. For example, if you now issue the call

ReplaceAt (testList, 7, objectZ);

testList will have the following contents:

Index Element
1 objectA
2 objectX
3 objectC
4 objectD
5 nilObject
6 nilObject
7 objectZ

AppendList

operation AppendList (listToAdd: Object)

Call: sometimes
Override: rarely

Call AppendList to add the items from a second object list to the end of the current list. AppendList calls AddTo once for each item in the second list. AppendList assumes that the list to be appended inherits from HasIndexing.

AppendListUnique

operation AppendListUnique (listToAdd: Object)

Call: sometimes
Override: rarely

Call AppendListUnique to add the items from a second object list that are not already in the current list to the end of the list. AppendListUnique calls AddUnique once for each item in the second list. AppendListUnique assumes that the list to be appended inherits from HasIndexing.

Searching

Search

operation Search (theElement: Object): Unsigned, noFail

Call: sometimes
Override: rarely

Call Search to search an object list for a given object. theElement is the desired object; Search returns the index of the first occurrence of this object in the list. If the requested object isn't in the list, the result is zero. As with many of the methods of ObjectList, Search first makes a storable version of the object (by calling MakeStorable), then calls FindElemAfter to perform the search.

For example, to find the index of the object testObject in a list named testList, you could make this Call:

ulong listIndex = Search (testList, testObject);

FindAfter

operation FindAfter (theElement: Object; afterIndex: Unsigned): Unsigned, noFail

Call: sometimes
Override: rarely

Call FindAfter to search an object list for a given object, beginning at a specified index position. theElement is the desired object; afterIndex is the index position at which to begin the search. FindAfter returns the index of the first occurrence of the requested object after the specified index in the list. If no such occurrence exists, the result is zero.

Notice that the search begins at the next object following the specified index, so a zero value for afterIndex searches the entire list. If afterIndex is less than zero or greater than the length of the list, the operation fails with the exception cannotFindIndex. If afterIndex is equal to the length of the list, FindAfter returns a zero result, indicating that the requested object could not be found after the last list element.

For example, assume that testList contains the following elements:

Index Element
1 ObjectA
2 ObjectB
3 ObjectC
4 ObjectD

Here are some example calls:

result = FindAfter (testList, objectC, 2);/* returns 3 */
result = FindAfter (testList, objectC, 3);/* returns 0 */
result = FindAfter (testList, objectB, 5);/* fails */
result = FindAfter (testList, objectC, 0);/* returns 3 */

FindElemAfter

overrides FindElemAfter (theElement: Pointer; afterIndex: Unsigned): 
Unsigned; noFail

Call: rarely
Override: rarely

The FindElemAfter operation, inherited from class FixedList, searches a list for a given element value, beginning at a specified index position. Class ObjectList overrides this method in order to apply a more efficient algorithm based on the knowledge that each element of the list is a 4-byte object ID. See the description of FixedList_FindElemAfter for more information.

Low-Level Object Management

DestroyContents

overrides DestroyContents

Call: rarely
Override: rarely

DestroyContents first removes then calls Destroy on each list element.