Part 12: Complex inheritance

 
 

12.1 Specification

        "Read the system data from file every morning when the system starts up, and write it to file every night when the system shuts down."
 
 

12.2 Analysis

        Two changes are made to the system. The first change adds file storage and retrieval. The second change uses multiple inheritance to separate the menu from the account classes.
 
 

12.3 Design: list storage and retrieval

        The list of customers is stored and retrieved by inheriting the class STORABLE in the BANK (to retrieve) and in the list class (to store). The inheritance chart for this part is:


 
 

12.4 Design: an inherited MENU

        The menu to an account should be separate from the account actions. This is done by deferring the actions in the MENU, effecting the features in the appropriate account, and joining the deferred and effective features by multiple inheritance. The class INTERACCT contains the effective features, so it will inherit the deferred MENU. The account inheritance hierarchy is:


 
 

12.5 Solution code

        Part of BANK, TELLER, ATM, MENU, and all of STORE_LIST are shown below.
 

class BANK

inherit
        STORABLE

creation
        make

feature {NONE}
        file_name: STRING is "patrons.dat"
        patrons: STORE_LIST[CUSTOMER]
        teller: TELLER
        atm: ATM

        make is
                        -- get the list of customers, run the system, store the data to file
               do
                       retrieve
                       !!teller.make (patrons)
                       !!atm.make (patrons)
                       run
                       store
               end -- make

        retrieve is
                        -- make or retrieve the list of customers
               local file: RAW_FILE
               do
                       !!file.make (file_name)
                       if file.exists then
                               file.open_read
                               patrons ?= retrieved (file)
                               file.close
                               show_retrieved
                       end
                       if patrons = Void then !!patrons.make end
               end -- retrieve

        show_retrieved is
                        -- show the number of records read from file
               do
                       io.putstring ("%N%T**** ")
                       io.putint (patrons.count)
                       io.putstring (" records read from file ****%N")
               end -- show_retrieved

        store is
                        -- store the list of customers
               local file: RAW_FILE
               do
                       !!file.make (file_name)
                       file.open_write
                       patrons.basic_store (file)
                       file.close
               end -- store

end -- class BANK
 

class STORE_LIST [T]

inherit
        STORABLE
        LINKED_LIST [T]

creation
        make

end -- class STORE_LIST
 

class TELLER

creation {BANK}
        make

feature {NONE}
        patrons: STORE_LIST [CUSTOMER]

feature {BANK}
        make (customersd: STORE_LIST [CUSTOMER]) is
                        -- store the list of customers
               do patrons := customers end -- make
        ...
end -- class TELLER
 

class ATM

creation {BANK}
        make

feature {NONE}
        patrons: STORE_LIST [CUSTOMER]

feature {BANK}
        make (customersd: STORE_LIST [CUSTOMER]) is
                        -- store the list of customers
               do patrons := customers end -- make
        ...
end -- class ATM
 

deferred class MENU

feature {ACCOUNTS}
        menu is
                        -- show the menu
                        -- get and execute menu choices

feature {NONE}
        do_choice is
                        -- execute the choice made by the user
               do
                       inspect io.lastchar.upper
                       when 'D' then do_deposit
                       when 'W' then do_withdraw
                       when 'B' then show_balance
                       when 'H' then show_choices
                       end -- inspect
               end -- do_choice

        do_deposit is
                        -- get the amount to deposit, then deposit it
               local amount: REAL
               do
                       io.putstring ("Enter the amount to deposit: ")
                       io.readreal
                       deposit (io.lastreal)
               end -- do_deposit

        do_withdraw is
                        -- get the amount to withdraw
                        -- if there is enough money, withdraw the amount
               local amount: REAL
               do
                       io.putstring ("Enter the amount to withdraw: ")
                       io.readreal
                       amount := io.lastreal
                       withdraw (amount)
               end -- do_withdraw

feature {NONE}
        deposit (amount: REAL) is
                        -- add the amount to the balance
               deferred
               end -- deposit

        withdraw (amount: REAL) is
                        -- withdraw this amount if there is enough money
               deferred
               end -- withdraw

        show_balance is
                        -- display the curent balance
               deferred
               end -- show_balance

end -- class MENU R>               deferred
               end -- show_balance

end -- class MENU