继承类属性而不声明属性或更好的OOP

2024-10-03 11:16:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图构造类来玩MTG游戏(一种纸牌游戏)。我有三个相关的类:MTGGame(…)、MTGCard(…)和AbilityList()。MTGGame的一个对象有几个关于玩家的属性(回合、法力、…、牌组)

玩家必须有一副牌才能玩,所以我为每个玩家创建了一个MTGCard对象列表,并从各自的牌组中为每个玩家创建了一个MTGGame对象。这些卡有能力,在创建卡时,我将能力作为函数/参数存储到每个MTGCard中然而,我需要从MTGGame继承和访问方法/属性并更新它们的能力,但是如果我使用super().__init__,那么在制作mtgcard时,我需要调用我的数据组作为AbilityList的参数,而我还没有

这能实现吗?如果没有,有什么建议可以改进我的OOP逻辑来完成这项任务吗

我知道我可以这样做:

class MTGGame():

    def __init__(self, deck, turn = 0, mana = 0, lifeTotal = 20, cavalcadeCount = 0, hand = [], board = []):   
        self.turn = turn
        self.mana = mana
        self.lifeTotal = lifeTotal
        ...
    def gainLife(self, lifeGained):
        self.lifeTotal = self.lifeTotal +lifeGained
    def combatPhase(self):
        for card in self.board:
            card.attackingAbility()

class MTGCard():

    def __init__(self, name, CMC, cardType, power, toughness, castedAbility, attackingAbility, activatedAbility, canAttack = False):
        ....
        self.attackingAbility = attackingAbility

Class abilityList():

    def healersHawkAbility(self, lifeAmt):
        MTGGame.gainLife(lifeAmt)

但这会影响MTGGame的所有实例,而不是从中调用的特定MTGGame对象。我希望它只是更新有问题的特定对象。我想这样做,但我不知道abilityList方法如何访问MTGGame属性/方法(“abilityList”对象没有属性“gainLife”):

Class abilityList():

    def healersHawkAbility(self, lifeAmt):
        #How do I access methods/attributes in MTGGame from here? self?
        self.gainLife(lifeAmt)

aL = abilityList()
#One example card:
card1 = MTGCard("Healers Hawk",1,'Creature',1,1, aL.nullAbility(), aL.healersHawkAbility, aL.nullAbility())
whiteDeck = [list of constructed MTGCard() objects, card1, card2,...,cardLast]
player1 = MTGGame(whiteDeck)
...

#Call the ability in a method contained in MTGGame:
player1.combatPhase()
#Would call something like this inside
card.attackingAbility()

#Which may refer to card.healersHawkAbility() since we stored healersHawkAbility() as an attribute for that MTGCard, 
#and would declare gainLife(), which refers to self.lifeTotal or player1.lifeTotal in this case.


Tags: 对象inself属性def玩家cardhealershawkability
1条回答
网友
1楼 · 发布于 2024-10-03 11:16:32

这是一个很好的开始,很明显你已经考虑了很多。但是,您还没有考虑到类之间的关系

首先要注意的是: MTGGame.gainLife(lifeAmt)是通过类而不是实例访问的方法调用。这意味着未实际填写自参数,即,由于您的方法需要2个参数,但只接收一个参数,因此将出现错误。 您可能想做的是:

class MTGGame:

    lifeTotal = 20 # Notice this is declared as a class variable

    def __init__(self, ...):
        ...

    @classmethod
    def healersHawkAbility(cls, lifeGained):
        cls.lifeTotal = cls.lifeTotal + lifeGained

然而,这需要类变量,这就破坏了拥有实例的意义

你在整个课程中的命名应该表明你的课程有点不对劲。 例如player1 = MTGGame()。玩家是游戏吗?不,当然不是。因此,实际上您可能想将类MTGGame重命名为Player,以明确它指的是玩家,而不是游戏。可能需要创建一个名为MTGGame的单独类来管理玩家之间的交互,例如轮到谁,解析时持有卡牌的堆栈

您问题的主要焦点:如何处理访问游戏/玩家对象的卡

卡牌应该能够访问玩家和游戏类的实例,如果玩家有is_playing属性,卡牌就不应该有这个属性。继承的经验法则是“是a”。由于卡牌“不是”玩家,它不应从卡牌或MTGGame继承。相反,卡片应如下所示,例如:

game = RevisedMTGGame()
player1 = Player()
player2 = Player()

class Card:
    def __init__(self, name, text, cost):
        self.name = name
        self.text = text
        self.cost = cost
        self.owner = None
        self.game = None

class Creature(Card):
    def __init__(self, name, text, cost, power, toughness):
        super().__init__(self, name, text, cost)
        self.power = power
        self.toughness = toughness
    def lifelink(self):
        self.owner.heal(self.power) # NOTE: this is NOT how I would implement lifelink, it is an example of how to access the owner

healersHawk = Creature("Healer's Hawk", "Flying, Lifelink", 1, 1, 1)
healersHawk.game = game
healersHawk.owner = player1

从这个不完整的示例中,您可以看到如何轻松地设置卡,即使使用复杂的机制,并且由于已经定义了基类,您可以避免重复编写代码。例如,为了实现lifelink机制,您可能需要研究事件模型。祝你继续比赛好运

相关问题 更多 >