#lang racket (require "02-sharing-data.rkt") ;; for the send function (provide make-account make-account make-interest-bearing-account) ;; ------------------------------------------------------------------------ ;; using a closure to implement a class (define make-account ;; class (let ((count 0)) ;; class variable (lambda (transaction) (case transaction ('new ;; constructor call = message (lambda (balance) ;; constructor method + inst var (set! count (+ count 1)) ; ------------------------------------------------------------ (lambda (transaction) ;; this is the object being returned (case transaction ('withdraw ;; instance message (lambda (amount) ;; instance method (if (>= balance amount) (begin (set! balance (- balance amount)) balance) (error "Insufficient funds" balance)))) ('deposit (lambda (amount) (set! balance (+ balance amount)) balance)) ('balance (lambda () balance)) (else (error "Unknown request -- ACCOUNT" transaction)))) )) ; ------------------------------------------------------------ ('count ;; class message (lambda () ;; class method count)) (else (error "Unknown request to BANK ACCOUNT class" transaction)))))) ;; (define eugene ((bank-account 'new) 100)) ;; ((eugene 'balance)) ;; ((eugene 'deposit) 100) ;; ((eugene 'balance)) ;; ((bank-account 'count)) ;; (define mary ((bank-account 'new) 100)) ;; ((bank-account 'count)) ;; ------------------------------------------------------------------------ ;; using copy-and-paste to implement a new kind of account ;; ------------------------------------------------------------------------ (define make-interest-bearing-account-v0 ;; COPY AND PASTE (lambda (balance ;; Creates a closure over balance interest-rate) ;; ** NEW ** and interest-rate. (lambda (transaction) (case transaction ('withdraw (lambda (amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) (error "Insufficient funds" balance)))) ('deposit (lambda (amount) (set! balance (+ balance amount)) balance)) ('balance (lambda () balance)) ('accrue-interest ;; NEW (lambda () ;; NEW (set! balance (* balance (+ 1.0 interest-rate))) ;; NEW balance)) ;; NEW (else (error "Unknown request -- ACCOUNT" transaction)))))) ;; ------------------------------------------------------------------------ ;; using delegation to simulate inheritance ;; ------------------------------------------------------------------------ (define make-interest-bearing-account (lambda (balance interest-rate) (let ((my-account (make-account balance))) ;; make a bank account to use (lambda (transaction) (case transaction ('accrue-interest (lambda () ((my-account 'deposit) (* ((my-account 'balance)) interest-rate)) )) (else (my-account transaction))))))) ;; delegate messages to it ;; ----------------------------------------------------------------------------