1. Defining the Object Model
1.3 Specifying Collections
Defining an instance variable as holding a Collection is done by specifying an empty example or template collection. This will define the class of collection, and also any additional information - e.g. the size for an Array. Supported collection classes are
Also a ListModel on: any of the other supported collection classes may be used.
The template collection must also specify the class of object held within that collection. This is done through the Collection method of: (for convenience, this is also defined as a class method which simply creates an empty collection). Note that at present the class of object held must be the same for all elements of that collection (except where inheritance is involved).
Array - When specifying an Array, remember that it is a fixed-size collection and so a size must always be given. Example:
define: #parents as: ((Array new: 2) of: Person)
SortedCollection - A SortedCollection used with ReStore is specified through the standard Smalltalk sortBlock mechanism (subject to certain rules). Examples:
"Use the sort order defined on Person (i.e. its implementation of <=)"
define: #relatives as: (SortedCollection of: Person)
"Define a custom sort "
define: #children as:
((SortedCollection sortBlock: [ :p1 :p1 | p1 dateOfBirth <= p2 dateOfBirth]) of: Person)
The use of sort blocks to specify a SortedCollection superceeds the previous method (sortAscendingBy:, sortDescendingBy:), which is retained for backwards compatibility.
Within ReStore, Collections specified as described above are termed General Collections. For those with knowledge of relational databases, they are stored using an intermediate table and can be considered as many-to-many collections.
Sometimes, collections exist which fulfill the following criteria:
- each member object appears in the collection only once
- each member object holds a reference to the owner of the collection
In this case, a more efficient form of collection can be used - an Owned Collection. This is equivalent to a one-to-many collection in relational database terminology. As an example, consider the classes Customer and Order in the Entertainment Shop example application. Customer has a collection of Orders each of which appears only once; each Order knows its customer (through its customer instance variable). Thus the Customer's orders collection can be specified as:
define: #orders as: (OrderedCollection of: Order owner: #customer)
(NB the application code defines orders as a ListModel on a SortedCollection;
these details are omitted here in order to highlight the underlying collection specification)
This defines the orders collection as an owned collection, with the Order instance variable customer holding a reference to the owning Customer.
Why use an owned collection? Owned collections are usually quicker to store and retrieve from the database than general collections. As a bonus, ReStore also automatically maintains the owner link - i.e. it would set the customer instance variable of an Order when it is added to a Customer's orders collection, and nil it out if the Order is subsequently removed.
It is worth considering specifying an owned collection if any of your classes have collections satisfying the required criteria. If in doubt, however, specify a General Collection.
1. Defining Classes
1.3 Specifying Collections