我正在阅读Python 3面向对象程序设计,但对其中一个示例有些困惑。是ch。 3,第78:
class AudioFile:
def __init__(self, filename):
if not filename.endswith(self.ext):
raise Exception("Invalid file format")
self.filename = filename
class MP3File(AudioFile):
ext = "mp3"
def play(self):
print("playing {} as mp3".format(self.filename))
因此,
MP3File
继承自AudioFile
。超类AudioFile
如何访问self.ext
?例如,Java有抽象类,因此不能保证AudioFile可以实例化/具有ext
字段。更重要的是,我认为子类继承了超类的所有信息,但没有另一个方向的信息流。看来我错了...
任何澄清都很好,
克莱曼
最佳答案
没错,我们不能保证AudioFile具有ext
属性。如果您要直接实例化AudioFile或编写一个未定义ext
的子类并将其实例化,则尝试访问self.ext
确实会失败。
因此,您可以将AudioFile视为一个抽象类,因为它依赖于其子类填充详细信息,以便AudioFile本身能够正常工作。但是在Python中,这种抽象性不是由语言编码的;您只需证明人们必须编写定义ext
的AudioFile子类,否则他们可能会遇到错误。 (其他一些抽象性也可以由abc
模块处理,尽管实际上它们通常也通过文档约定进行处理。)
至于AudioFile如何访问存在的属性。 。 。好吧,它是在实例而不是类上访问它。用MP3File
之类的实例化obj = MP3File()
后,便有了一个实例对象obj
。在该对象上执行obj.ext
将返回其ext
属性,或者,如果该实例没有其自身的属性,它将在其类中查找该属性(然后在其超类中一直查找)。每次您尝试访问属性时,都会动态发生此属性查找。您不能也不可以“预先声明”将在哪里找到属性(在实例,类或层次结构上的某些超类中)。因此,当同时也是AudioFile
的MP3File
执行self.ext
时,它会在MP3File
上找到属性,因为self
是MP3File
的实例。
如果这本书没有解释这方面的任何内容,那么那个例子可能不是最好的例子。它可以工作,但是对于具有不同OO语义的其他语言的用户来说,它的工作方式并不明显。另外,即使您确实了解Python,在现实世界中,使文档告诉您如何使用AudioFile
也很重要(即说“您必须对此子类化,并且您的子类必须定义ext
)。
关于python - Python中的基本多态性混淆,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31862883/