正确使用具有多重继承的方法重写?

Proper use of method overriding with multiple inheritance?

假设我有两个 class 像 Mp3PlayerDVDPlayer 我要创建一个新的 class MultiPlayer 继承自两者前 classes.

Mp3PlayerDVDPlayer 都有一个具有相同签名的方法:

class MP3Player:

    def play(self, content):
        print(f'MP3 player is playing {content}')


class DVDPlayer:

    def play(self, content):
        print(f'DVD player is playing {content}')

我想覆盖 MultiPlayer 中的 play 方法,并且我希望能够根据某些条件调用适当的超级 class。

class MultiPlayer(MP3Player, DVDPlayer):

    def play(self, content):
        if mp3_condition:
            # some how call the play method in MP3Player
        elif dvd_condition:
            # some how call the play method in DVDPlayer
        else:
            print('the given content is not supported')

我不能使用 super().play(content),因为根据 MRO 规则,它总是解析为 MP3Player 中的 play 方法。

做这种事情的 pythonic 方式是什么?

我会显式调用 play 方法:

class MultiPlayer(MP3Player, DVDPlayer):

    def play(self, content):
        if mp3_condition:
            MP3Player.play(self, content)
        elif dvd_condition:
            DVDPlayer.play(self, content)
        else:
            print('the given content is not supported')

注意。 — 如果你绝对想使用 super(),你可以这样做:

class MultiPlayer(MP3Player, DVDPlayer):

    def play(self, content):
        if mp3_condition:
            super().play(content)
        elif dvd_condition:
            super(MP3Player, self).play(content)
        else:
            print('the given content is not supported')

但我会避免它,因为 它假定 MP3PlayerMP3Player 的共同祖先之间没有 class 和 play 方法和DVDPlayer(即这里的object)。如果稍后您改变主意并引入这样的 class,super(MP3Player, self).play(content) 将调用此 class 的 play 方法,而不是您预期的 DVDPlayer.play 方法。 class 不应该在其基础 classes.

的层次结构中假设任何东西

此外,super(MP3Player, self).play(content)DVDPlayer.play(self, content)更难理解,而且还需要明确的class名称。因此,除了松散的灵活性和清晰度之外,您一无所获。

为了更好地理解 super() 在 Python 中的工作原理,我强烈推荐 Raymond Hettinger 的优秀文章 Python’s super() considered super!

当您使用继承时,您是说子class 父class的一种类型,只是一种更特殊的类型。这称为 is-a 关系。

一个常见的例子是用动物来说明这一点。假设您有三个 classes:Animal、Cat 和 Lion。狮子 猫,而猫 动物,因此在这种情况下使用继承是有意义的。

但是你的情况不同。您有一个 MultiPlayer class,通过使用继承,您说它 一个 MP3 播放器,而且它 也是 DVD 播放器。

这可以工作,但是在这种情况下使用 组合 而不是 继承 更自然。组合是 has-a 关系而不是 is-a,这意味着您的多人游戏 class has 里面有一个 MP3 播放器,它还有 一个 DVD 播放器,但是 根本上 两者都不是.