显式调用父类方法
讲解如何使用 usual 关键字显式调用父类(祖先类)中定义的同名方法,以及 usual 的命名由来。
调用父类
我们的企鹅类越来越拥挤了!为了整洁起见,我们给它做一个子类,叫 emperor-penguin(帝企鹅)。它能做 penguin 能做的一切,只不过在吃东西时,emperor-penguin 会先说一句 '(bon apetit)(好胃口!)。下面的定义能行吗?
(define-class (emperor-penguin name)
(parent (penguin name))
(method (eat)
(print '(bon apetit!))
(ask self 'eat)))
笔记
测试你的理解
假设我们这样定义 napoleon:
(define napoleon (instantiate emperor-penguin 'napoleon))
当我们调用 (ask napoleon 'eat) 时会发生什么?
usual 的用法
调用父类方法的正确方式是使用 usual 关键字。
(define-class (emperor-penguin name)
(parent (penguin name))
(method (eat)
(print '(bon apetit!))
(usual 'eat)))
usual 接受一个或多个参数,第一个是消息,其余是该消息需要的参数。这个消息及必要的参数随后会被传给父类。这样一来,emperor-penguin 对象引用的就是 penguin 的 eat 方法。
调用 usual 就像用相同的参数说 (ask self ...),只不过只有祖先类(父类、祖父类等)中定义的方法才有资格被调用。如果一个类没有父类,调用 usual 就是错误的。
命名的直觉
你可能觉得 usual 这个函数的名字有点怪。这个名字背后的想法是:我们把子类看作特化。也就是说,父类代表某个宽泛的事物范畴,而子类是特化的版本。(可以想想支票账户与一般 account 账户之间的关系。)子类对象做事的方式几乎和父类一样。子类会用一些特殊方式处理少数消息,不同于通常的做法(即父类的做法)。但子类也可以显式决定用通常的(类似父类的)方式做事,而不是用它自己的特化方式。