#lang racket
(define Message%
(class object%
(init aString)
(field (text aString))
(super-new)
(define/public (printIt)
(println text))))
(define Square%
(class object%
(init side)
(field (this-side side))
(super-new)
(define/public (calculateArea)
(expt this-side 2))))
(define Circle%
(class object%
(init radius)
(field (this-radius radius))
(super-new)
(define/public (calculateArea)
(* pi (expt this-radius 2)))))
(define BalanceError "現在の口座残高は~aしかありません。")
(define BankAccount%
(class object%
(init initialAmount)
(field (balance initialAmount))
(printf "口座を開設しました。口座残高は~aです。~%" balance
) (super-new)
(define/public (deposit amount)
(set! balance (+ balance amount)))
(define/public (withdraw amount)
(if (>= balance amount)
(set! balance (- balance amount))
(error 'BalanceError BalanceError balance)))
(define/public (getBalance)
balance)
(define/public (transfer amount account)
(with-handlers ((exn:fail?
(lambda (exn)
(printf BalanceError balance)
(newline))))
(withdraw amount)
(send account deposit amount)))))
(define InterestAccount%
(class BankAccount%
(super-new)
(inherit-field balance)
(define/override (deposit amount)
(super deposit amount)
(set! balance (* balance 1.03)))))
(define ChargingAccount%
(class BankAccount%
(super-new)
(init-field (fee 3))
(define/override (withdraw amount)
(super withdraw (+ amount fee)))))
(module+ main
(define m1 (new Message% (aString "Hello world")))
(define m2 (new Message% (aString "楽しかったです。さようなら。")))
(define note `(,m1 ,m2))
(for-each (lambda (msg)
(send msg printIt)) note)
(define lst `(,(new Circle% (radius 5))
,(new Circle% (radius 7))
,(new Square% (side 9))
,(new Circle% (radius 3))
,(new Square% (side 12))))
(for-each (lambda (shape)
(printf "面積は、~a~%" (send shape calculateArea))) lst)
;; 標準のBankAccountのテスト
(define a (new BankAccount% (initialAmount 500)))
(define b (new BankAccount% (initialAmount 200)))
(send a withdraw 100)
;; (send a withdraw 1000)
(send a transfer 100 b)
(printf "A=~a~%" (send a getBalance)) ; 300になる
(printf "B=~a~%" (send b getBalance)) ; 300になる
;; InterestAccount のテスト
(define c (new InterestAccount% (initialAmount 1000)))
(send c deposit 100)
(printf "C=~a~%" (send c getBalance)) ; 1133になる
;; ChargingAccountのテスト
(define d (new ChargingAccount% (initialAmount 300)))
(send d deposit 200)
(printf "D=~a~%" (send d getBalance)) ; 500になる
(send d withdraw 50)
(printf "D=~a~%" (send d getBalance)) ; 447になる
(send d transfer 100 a)
(printf "A=~a~%" (send a getBalance)) ; 400になる
(printf "D=~a~%" (send d getBalance)) ; 344になる
;; 最後に、ChargingAccountからInterestAccountに振り込みする
;; ChagingAccountでは振り込み手数料が発生し、
;; InterestAccountでは利息が発生する
(printf "C=~a~%" (send c getBalance)) ; 1133である
(printf "D=~a~%" (send d getBalance)) ; 344である
(send d transfer 20 c)
(printf "C=~a~%" (send c getBalance)) ; 1187.59である
(printf "D=~a~%" (send d getBalance)) ; 321になる
)