Self-reference

Chapter: Self-reference

One finds that it is often useful for a method to call another method of the same object. For example, in implementing our bank account object, we might not want to implement the method for add-interest directly; we could instead simply call deposit to deposit the appropriate amount. This requires the creation of a local name for the object. Following the conventions of the C++ and Java programming languages, we use the name this to refer to the local object. Thus to call methods of our own object we use the keyword call just as in previous method calls but we use the object name this:

(call METHOD-NAME this ARGUMENTS)

This works because this is simply another instance variable.

Here is the bank class rewritten to use the deposit method to add interest to the account. Note the use of call and this:

(define Bank-class
  (class (bank-code user-pin)
    ([balance 0]
     [interest-rate 0.025]
     [output (lambda () (printf "The balance is $~s~%" balance))])
    (Object)
    ([deposit
      (method (amount)
	(if (> amount 0)
	    (begin
	      (set! balance (+ balance amount))
	      (output))))]
     [withdraw
      (method (amount pin)
        (if (and (= user-pin pin) (> amount 0) (>= balance amount))
	    (begin
	      (set! balance (- balance amount))
	      (output))
	    (error 'withdraw 
		   "check your pin or withdrawal amount")))]
     [add-interest
      (method (code)
	(if (= code bank-code)
            (begin
	      (call deposit this (* balance interest-rate)) ;self reference
	      (output))
	    (error 'add-interest "invalid bank access code")))]
	)))

The expression:

(call deposit this (* balance interest-rate))
makes use of the existing deposit method. This ability to reuse code is an aspect of object oriented programming which will become most important in the next section.

Can you fix the repetitive announcement of the balance?

> (define acc (Bank-class 1234 4321))
> (call deposit acc 2000)
The balance is $2000
> (call add-interest acc 1234)
The balance is $2050.0
The balance is $2050.0

How does it work?

> (expand '(call add-interest acc 1234))
((lambda (#{instance xqs1tou25ojmrof-b})
   ((lookup-method 'add-interest #{instance xqs1tou25ojmrof-b})
     #{instance xqs1tou25ojmrof-b}
     1234))
  acc)
> (expand '(method (x) body))
(lambda (#{this xqs1tou25ojmrof-c} #{x xqs1tou25ojmrof-d})
  body)
> 

or, stripped of the hygiene weirdness:

> (expand '(call add-interest acc 1234))
((lambda (instance)
   ((lookup-method 'add-interest instance)
     instance
     1234))
  acc)
> (expand '(method (x) body))
(lambda (this x)
  body)
> 

or, restoring the let syntactic sugar removed by expand:

> (expand '(call add-interest acc 1234))
(let ((instance acc))
   ((lookup-method 'add-interest instance)
     instance
     1234))
> (expand '(method (x) body))
(lambda (this x)
  body)
> 


rhyspj@gwu.edu