;; A fish class (define (mk-fish size) (letrec ([get-size (lambda () size)] [grow (lambda (s) (set! size (+ s size)))] [eat (lambda (fish) (grow ((fish 'get-size))))]) (lambda (msg) (cond [(eq? msg 'get-size) get-size] [(eq? msg 'grow) grow] [(eq? msg 'eat) eat])))) ;; Derived class (define (mk-colorfish size) (let ([fish (mk-fish size)] [color 0]) (letrec ([get-color (lambda () color)] [set-color (lambda (c) (set! color c))]) (lambda (msg) (cond [(eq? msg 'get-color) get-color] [(eq? msg 'set-color) set-color] [else (fish msg)]))))) ;; Dervied class with overriding (define (mk-pickyfish size) (let ([fish (mk-fish size)]) (letrec ([grow (lambda (s) ((fish 'grow) (- s 1)))]) (lambda (msg) (cond [(eq? msg 'grow) grow] ;; Oops - eat won't use ;; the right grow method [else (fish msg)]))))) ;; The problem with pickyfish could be fixed. ;; The point is that we *could* implement objects ;; with functions, but it's more convenient to ;; have special constructs for objects.