(define-class <bank-account> () ((dollars :accessor dollars :init-value 0 :init-keyword :dollars))) (define-method dollars ((self <bank-account>) x) (set! (dollars self) x)) (define-method deposit ((self <bank-account>) x) (dollars self (+ (dollars self) x))) (define-method withdraw ((self <bank-account>) x) (dollars self (max 0 (- (dollars self) x)))) (define my-account (make <bank-account> :dollars 200)) (dollars my-account) ==> 200 (deposit my-account 50) (dollars my-account) ==> 250 (withdraw my-account 100) (dollars my-account) ==> 150 (withdraw my-account 200) (dollars my-account) ==> 0 (define-class <stock-account> (<bank-account>) ((num-shares :accessor num-shares :init-value 0 :init-keyword :num-shares) (price-per-share :accessor price-per-share :init-value 30 :init-keyword :price-per-share))) (define-method num-shares ((self <stock-account>) x) (set! (num-shares self) x)) (define-method price-per-share ((self <stock-account>) x) (set! (price-per-share self) x)) (define-method dollars ((self <stock-account>) x) (num-shares self (/ x (price-per-share self)))) (define-method dollars ((self <stock-account>)) (* (num-shares self) (price-per-share self))) (define my-stock (make <stock-account> :num-shares 10)) (dollars my-stock) ==> 300 (dollars my-stock 600) (dollars my-stock) ==> 600 (deposit my-stock 60) (dollars my-stock) ==> 660 (num-shares my-stock) ==> 22 (withdraw my-stock 120) ==> 540 (num-shares my-stock) ==> 18
今の私の知識ではこれがバグかどうかは分からないのですが、:accessor オプションでゲッターを自動的に定義すると、サブクラスで同名のメソッドをオーバーライド(総称関数に登録)していても、サブサブクラスでは隔世遺伝してしまう(サブクラスでオーバーライドしたメソッドではなく、:accessor オプションがゲーターとして自動登録したメソッドが起動してしまう)という不都合があるようです。そこで、:accessor オプションは使わず、手でゲーター、セッターを同名メソッドで登録しています。--sumim(define-class <bank-account-meta> (<class>) ((dollars :init-value 0))) (define-class bank-account () () :metaclass <bank-account-meta>) (define-method dollars ((self <bank-account-meta>)) (slot-ref self 'dollars)) (define-method dollars ((self <bank-account-meta>) x) (slot-set! self 'dollars x)) (define-method deposit ((self <bank-account-meta>) x) (dollars self (+ (dollars self) x))) (define-method withdraw ((self <bank-account-meta>) x) (dollars self (max 0 (- (dollars self) x)))) (dollars bank-account 200) (dollars bank-account) ==> 200 (deposit bank-account 50) (dollars bank-account) ==> 250 (withdraw bank-account 100) (dollars bank-account) ==> 150 (withdraw bank-account 200) (dollars bank-account) ==> 0 (define-class <my-account-meta> (<bank-account-meta>) ()) (define-class my-account () () :metaclass <my-account-meta>) (dollars my-account 500) (dollars my-account) ==> 500 (dollars bank-account) ==> 0 (define-class <stock-account-meta> (<bank-account-meta>) ((num-shares :init-value 0) (price-per-share :init-value 30))) (define-class stock-account () () :metaclass <stock-account-meta>) (define-method num-shares ((self <stock-account-meta>)) (slot-ref self 'num-shares)) (define-method num-shares ((self <stock-account-meta>) x) (slot-set! self 'num-shares x)) (define-method price-per-share ((self <stock-account-meta>)) (slot-ref self 'price-per-share)) (define-method price-per-share ((self <stock-account-meta>) x) (set! (price-per-share self) x)) (define-method dollars ((self <stock-account-meta>) x) (num-shares self (/ x (price-per-share self)))) (define-method dollars ((self <stock-account-meta>)) (* (num-shares self) (price-per-share self))) (num-shares stock-account 10) (dollars stock-account) ==> 300 (dollars stock-account 150) (dollars stock-account) ==> 150 (num-shares stock-account) ==> 5 (define-class <my-stock-meta> (<stock-account-meta>) ()) (define-class my-stock () () :metaclass <my-stock-meta>) (dollars my-stock 600) (dollars my-stock) ==> 600 (num-shares my-stock) ==> 20 (num-shares stock-account) ==> 5 (deposit my-stock 60) (dollars my-stock) ==> 660 (num-shares my-stock) ==> 22 (withdraw my-stock 120) (dollars my-stock) ==> 540 (num-shares my-stock) ==> 18
このページを編集 (6968 bytes)
以下の 3 ページから参照されています。 |
This page has been visited 6030 times.