7.3.2 覆写

子类除了原样继承超类的方法,还可以修改继承来的超类方法,以便以自己的方式行事。 这种在子类中重新定义超类方法的情况是面向对象的又一特色,称为覆写(override,或称重 定义)。

例如,我们来定义另一类特殊的人——娱乐圈明星。娱乐圈明星当然是人,所以他们都 具有 Person 的属性。但明星们一般都很忌讳被问年龄,他们才不会像普通人那样直接回答 howOld 问题。因此,我们在定义 Star 类时需要重新实现 howOld 方法,不能直接使用 Person 中定义的 howOld 的代码。Star 定义如下:

class Star(Person): 
def howOld(self,y):
    print "You guess?" 
def setYear(self,y):
    self.year = y

类 Star 中重新定义了 howOld()方法,将来向 Star 对象发送 howOld 信息时,它就会执行自己 独特的 howOld 方法。当然,如果向 Star 对象发送 whatName 消息,由于明星们在这个问题 上与常人无异,该对象就会去执行原样继承来的超类 Person 中的 whatName 方法。顺便指出, 上述 Star 类定义中还定义了一个特殊方法 setYear,这是为了满足某些明星直接修改自己出生 年份的需求:-),同时也是为了说明子类既可以覆写从超类继承来的行为,也可以干脆定义新 的行为。下面是 Star 类的使用例子(假设 Star 类定义已经导入):

>>> liu = Star("Liu",1955)
>>> liu.whatName()
My name is Liu
>>> liu.howOld(2013)
You guess?

注意,覆写是指在子类中重新实现超类的方法,该方法的调用界面(参数和返回值)是 不能改变的。另外,子类中覆写的方法仅适用于子类对象,并不能取代超类中的对应方法。 还用上述例子,当向 Person 类的实例发送 howOld 消息时,仍会执行原来的 howOld 代码。 有趣的是,由于 Star 对象也是 person 对象,我们甚至能强迫 Star 对象执行 Person 中的 howOld 方法来如实回答年龄,做法如下(参见图 7.8):

>>> Person.howOld(liu,2013)
My age in 2013 is 58