In today's lecture we look at aggregation and how it affects the use and copying of objects.
The material covered reflects Chapter 8 of the 3rd Edition of the textbook (there are significant differences between the 2nd and 3rd Editions in Section 8.2).
Call number of textbook on reserve in Steacie: PCOP.2629STEACIE
Sometimes a client will want to create a copy of an object. The cleanest way to copy an object is to use what is called a copy constructor, but many existing classes do not provide them. In these cases, the client has to do some extra work.
The simplest form of copying an object is to create an alias:
Investment inv = new Investment(new Stock("HR.A"), 10, 2.00); Investment alias = inv;
Investment inv = new Investment(new Stock("HR.A"), 10, 2.00); Investment alias = inv;
inv ⇒ | 400 | |
alias ⇒ | 400 | |
| | ||
400 | Investment object | |
stock ⇒ | 500 | |
| | ||
500 | Stock object | |
When you create an alias, you are referring to an
existing object; inv
and alias
both refer to the Investment
object
at address 400
.
How can you tell if a copy is an alias?
Use ==
.
boolean isAlias = (inv == alias);
This also applies to references returned by accessors.
A shallow copy of an object creates a new object with attributes that are identical to the original object. If the original object is an aggregation, then the copied object aggregates the same objects as the original.
Investment inv = new Investment(new Stock("HR.A"), 10, 2.00); Investment shallow = new Investment(inv.getStock(), inv.getQty(), inv.getBookValue());
Investment inv = new Investment(new Stock("HR.A"), 10, 2.00); Investment shallow = new Investment(inv.getStock(), inv.getQty(), inv.getBookValue());
inv ⇒ | 400 | |
shallow ⇒ | 500 | |
| | ||
400 | Investment object | |
stock ⇒ | 600 | |
| | ||
500 | Investment object | |
stock ⇒ | 600 | |
| | ||
600 | Stock object | |
When you create a shallow copy, you create a new object but that object contains aliases to existing objects.
How can the client show that shallow
is (probably) a shallow copy of inv
?
Check to see if object references returned by accessors
are aliases.
boolean isShallow = (inv.getStock() == shallow.getStock());
In the above code fragment isShallow
is
true
indicating
that stock aggregated by inv
is the same object
as the stock aggregated by shallow
.
Note that if getStock
returns a copy of a stock
then there is no way for the client to make a shallow copy
of inv
in this example.
Copy constructors can also create shallow copies; you have to read the API of the class you are copying.
Investment(Investment investment)
Construct a (shallow) copy of the passed Investment.
A deep copy of an object creates a new object with attributes that are copies of those of the original object. If the original object is an aggregation, then the copied object aggregates different objects as the original.
Investment inv = new Investment(new Stock("HR.A"), 10, 2.00); // create a deep copy of the aggregated Stock Stock s = new Stock(inv.getStock().getSymbol()); // create a deep copy of the Investment Investment deep = new Investment(s, inv.getQty(), inv.getBookValue());
Investment inv = new Investment(new Stock("HR.A"), 10, 2.00); // create a deep copy of the aggregated Stock Stock s = new Stock(inv.getStock().getSymbol()); // create a deep copy of the Investment Investment deep = new Investment(s, inv.getQty(), inv.getBookValue());
inv ⇒ | 400 | |
s ⇒ | 700 | |
deep ⇒ | 500 | |
| | ||
400 | Investment object | |
stock ⇒ | 600 | |
| | ||
500 | Investment object | |
stock ⇒ | 700 | |
| | ||
600 | Stock object | |
| | ||
700 | Stock object | |
When you create a deep copy, you create a new object and that object contains references to newly created objects.
How can the client show that deep
is (probably) a deep copy of inv
?
Check to see if object references returned by accessors are
not aliases.
boolean isDeep = (inv.getStock() != deep.getStock());
In the above code fragment isDeep
is true
indicating
that stock aggregated by inv
is a different object
from the stock aggregated by deep
.
A collection is an object that groups multiple object references into a single unit. You can think of a collection as representing a container for objects where each object is usually referred to as an element.
Remember that there are significant differences between the 2nd and 3rd Editions of the textbook in Section 8.2.
Call number of textbook on reserve in Steacie: PCOP.2629STEACIE
Because a collection groups multiple object references, it is an aggregation. Typically, a collection aggregates elements that form a natural group. For example:
Collection Of | Represents |
at most 23 hockey players | National Hockey League team roster |
at most 7 playing cards | Texas Holdem poker hand |
words | dictionary |
books | library |
Notice that some collections have a natural maximum capacity, whereas the size of other collections naturally grows and shrinks.
In the case of a collection with a known maximum capacity, it is possible to allocate enough memory to store the collection when the collection is created; this is called static allocation (where static means unchanging and is not related to the Java keyword).
In the case where the size of the collection can grow and shrink, memory is allocated as it is needed, which is called dynamic allocation.
The Portfolio
class is an example of a statically
allocated collection. It represents a collection of Investment
objects.
// no name portfolio with capacity 100 Portfolio pf = new Portfolio(); // named portfolio with capacity 50 Portfolio myPf = new Portfolio("My Retirement Fund", 50);
Note that the capacity of a collection is different than its size. The capacity of a portfolio is the maximum number of investments that it can hold. The size of a portfolio is the actual number of investments in the portfolio.
GlobalCredit
is an example of a dynamically allocated
collection. It represents a collection of credit cards (presumably
distributed by a bank).
// an empty collection of credit cards GlobalCredit cards = new GlobalCredit();
Some collections have constructors where the client can specify
an initial capacity of the collection, but GlobalCredit
does not have such a constructor.