【问题标题】:How to access a child class method from a parent class?如何从父类访问子类方法?
【发布时间】:2019-04-24 04:32:41
【问题描述】:

有很多答案说这是不可取的,但我发现了一个我认为它很有用的场景。如果我错了,请纠正我,并且有更好的方法。

我正在构建一个国际象棋游戏,其中单个棋子继承自超类 Chesspiece

class ChessPiece:
    def __init__(self, pos, color, num, piece):
        ...

每个棋子都有一个方法来定义它可以采取的动作:

class Knight(ChessPiece):
    def __init__(self, pos, color=None, num=''):
        ChessPiece.__init__(self, pos, color, num, self.__class__.__name__)


    def possible_moves(self):
        pos_moves = []

        # Up, Right (1 space, 2 spaces)
        try:
            if 1 <= self.x + 2 <= len(Config.board) and 1 <= self.y - 1 <= len(Config.board):
                if Config.board[self.x + 2][self.y - 1] == '___':
                    pos_moves.append(f'{Config.tile_convert(self.x + 2)}{Config.tile_convert(self.y - 1, True)}')

        except Exception: pass

        #Up, Left
        ...

        return pos_moves

我想实现一个move() 函数。 move() 函数的代码对于每一块都是相同的,除了它必须将建议的移动与可能的移动进行比较,这对于每一块都不同。我可以为每个部分创建一个move() 函数,但这只会重复代码 6 次。

所以,我想在Chesspiece 中定义move() 并引用每个部分的possible_moves() 函数。

【问题讨论】:

  • 是什么让你觉得你需要做一些特别的事情?只需调用该方法。 (如果需要,您可以在基类中定义 abstract method,它实际上可能会有所帮助,但您不需要这样做。)
  • 如果你初始化一个Knight实例,它将有move()possible_moves()方法。所以没有问题。您可能想要实现一个虚拟的possible_moves(),它只会在基类中引发NotImplemented,以防止您的IDE 抱怨。
  • 另外,except Exception: pass 是个糟糕的主意。那种东西只是隐藏错误。不要掉进那个陷阱。
  • 如果棋子无法移动,有时会引发异常。您是否建议我使用它引发的特定异常?因为如果确实发生异常,除了通过之外别无他法。
  • possible_moves 中引发或捕获异常是没有意义的。为无效移动引发异常应该发生在move,而不是possible_moves,并且possible_moves 不应该与此类异常交互。

标签: python python-3.x class inheritance


【解决方案1】:

在父级中实现一个空的possible_moves 更简单:

class ChessPiece:
    ...
    def possible_moves(self):
        raise NotImplementedError

    def move(self, pos):
            if pos in self.possible_moves():
            ...

甚至在父类中返回一组空的动作:

def possible_moves(self):
    return set()

但我认为第一个更好,所以它强制所有子类实现它才能有用。

【讨论】:

  • 但可能的移动算法因每件而异
  • 这就是为什么你需要为每个部分实现它@alec_a
  • 这是可能的,但实际上不是必需的。此外,NotImplementedError 是个例外。 NotImplemented 是运算符重载方法在不理解其参数时应该返回的内容。
  • @Netwave 哦,我现在明白了。您可以使用self 调用该方法。
  • 在超类中定义它并在调用时引发错误有什么意义?
猜你喜欢
  • 2021-07-09
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 1970-01-01
  • 2014-10-04
  • 2017-09-22
  • 1970-01-01
相关资源
最近更新 更多