The specification is unchanged from the previous case study.
There is no analysis because the specification is unchanged.
Constrained genericity is used to move the list scan code from ATM and
TELLER to KEY_LIST [T]. Class KEY_LIST can be used to
store and retrieve any object with an integer key. The minimum that we
need is to define a keyed list of customers, but a more general solution
is shown that works for any object with an INTEGER key. The construction
of a class that is a keyed list requires a deferred class that has a key
and a match routine (class KEY) a child that inherits this parent
and effects the match routine (class CUSTOMER) and a constrained
generic class (class KEY_LIST) The constrained class has KEY
as its constraint in the class header, and contains code to look up an
element of the list using a key.
13.5 Design: a keyed, storable list
A keyed, storable list class is created by combining the inheritance hierarchies
from the two applications, and moving the lookup code from the clients
(TELLER and ATM) into the keyed class. The inheritance hierarchy
for the keyed, storable list class is shown below.
A full listing for class KEYED is shown below, then its inheritance
in CUSTOMER The following pages shows the client code to use a keyed
list in TELLER and ATM, followed by a full listing for KEY_LIST
.
class KEYED
feature {NONE}
id: INTEGER
feature {ANY}
set_id (key: INTEGER)
is
-- store the key in id
do
id := key
end -- set_id
match (key: INTEGER):
BOOLEAN is
-- does the key match the id?
do
Result := key = id
end -- match
show_id is
-- show the customer id
do
io.putstring ("%NThe customer id is ")
io.putint (id)
end -- show_id
end -- class KEYED
class CUSTOMER
inherit
KEYED
PERSON
...
end -- class CUSTOMER
class TELLER
creation {BANK}
make
feature {NONE}
patrons: KEY_LIST[CUSTOMER]
make (customers: KEY_LIST
[CUSTOMER]) is
-- store the customers in patrons
do patrons := customers end -- make
...
new_accounts is
-- add any new accounts for existing customers
do
from ask_for_more_accounts
until no_more
loop
read_id
patrons.find (io.lastint)
if patrons.found
then patrons.item.accounts.make
else io.putstring ("%NThat is not a valid userId")
end
ask_for_more_accounts
end
end -- new_accounts
...
end -- class TELLER
class ATM
creation {BANK}
make
feature {NONE}
patrons: KEY_LIST [CUSTOMER]
make (customers: KEY_LIST
[CUSTOMER]) is
-- store the customers in patrons
do patrons := customers end -- make
...
serve_customer (id: INTEGER)
is
-- find the customer with the input id
-- if the customer exists, transfer control
do
patrons.find (id)
if patrons.found
then patrons.item.login
else io.putstring ("%NThat is not a valid userId")
end
end -- serve_customer
...
end -- class ATM
class KEY_LIST [T -> KEYED]
inherit
STORABLE
LINKED_LIST [T]
creation {BANK}
make
feature {TELLER, ATM}
get_id is
-- get a customer's user identifier
do
io.putstring ("%N%TEnter user id: ")
io.readint
end -- get_id
find (key: INTEGER)
is
-- set the cursor at the person with this key
-- if no such person, cursor is offright
do
from start
until after or else item.match (key)
loop forth
end
end -- find
found: BOOLEAN is
-- is the cursor in the list?
do
Result := not after
end -- found
end -- class KEY_LIST