文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
6.2 方法查找
当给对象发送消息时,我们在它的类中查找实现此消息的方法,然后调用之。反映到 CLASS
宏的定义中就是:
[(invoke)
(if (assoc (second vals) methods)
(apply ((cdr (assoc (second vals) methods)) (first vals)) (cddr vals))
(error "message not understood"))]
有了继承,在对象收到一个在其类中找不到方法的消息时,我们可以在超类中寻找方法,并依此类推。首先, invoke
协议需要修改,将其分成两步:第一步是 lookup
(查找),包括当前类中没有找到方法时在超类中进行查找,第二步是实际的 invoke
步骤。
(defmac (CLASS extends superclass
([field f init] ...)
([method m params body] ...))
#:keywords field method extends
#:captures self ? !
(let ([scls superclass]
(methods
(local [(defmac (? fd) #:captures self
((obj-class self) 'read self 'fd))
(defmac (! fd v) #:captures self
((obj-class self) 'write self 'fd v))]
(list (cons 'm (λ (self)
(λ params body))) ...))))
(letrec ([class (λ (msg . vals)
(case msg
....
[(invoke)
(let ((method (class 'lookup (second vals))))
(apply (method (first vals)) (cddr vals)))]
[(lookup)
(let ([found (assoc (first vals) methods)])
(if found
(cdr found)
(scls 'lookup (first vals))))]))])
class)))
CLASS
语法抽象扩展了,加了 extends
子句(这是类定义中新的关键字)。试用这个抽象之前,我们需要在树的顶部定义一个 根 类,以终结方法查找的过程。如下的 Root
类就可以:
(define Root
(λ (msg . vals)
(case msg
[(lookup) (error "message not understood:" (first vals))]
[else (error "root class: should not happen: " msg)])))
Root
直接实现为函数而不使用 CLASS
形式,所以我们无需指定它的超类(它也没有)。如果收到 lookup
消息,它会给出消息无法理解的错误。请注意,在此系统中,除了 lookup
以外的任何消息发送到根类都是错误。
来看一个非常简单的类继承的例子:
(define A
(CLASS extends Root ()
([method foo () "foo"]
[method bar () "bar"])))
(define B
(CLASS extends A ()
([method bar () "B bar"])))
> (define b (new B))
> (-> b foo)
"foo"
> (-> b bar)
"B bar"
看起来都对了:向 B
发送其不理解的消息效果正如预期,并且发送 bar
的结果是 B
中调整过而不是 A
中的方法被执行。换一种说法,方法调用被正确的 延迟绑定 (late binding)。我们说, B
中的 bar
方法 覆盖 (override)了 A
中定义的同名方法。
再来看个稍微复杂一点的例子:
> (define p (new Point))
> (-> p move 10)
> (-> p x?)
10
来试试 ColorPoint
:
> (define cp (new ColorPoint))
> (-> cp color! 'red)
> (-> cp color?)
'red
> (-> cp move 5)
hash-ref: no value found for key
key: 'x
发生了什么?看来,我们不能使用 ColorPoint
的 x
字段。好吧,我们还没有讨论过在继承中如何处理字段。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论