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



我正在尝试构建类来玩MTG(纸牌游戏(游戏。我有三个相关的类:MTGGame(...(,MTGCard(...(和AbilityList((。MTGGame 的对象具有关于玩家的多个属性(回合、魔法,...,套牌(。

玩家必须有一副牌才能玩,因此我为每个玩家创建一个 MTGCard 对象列表,并从各自的牌组中为每个玩家创建一个 MTGGame 对象。卡牌具有能力,在创建卡牌时,我将能力作为函数/参数存储到每个MTGCard中。但是,我需要从 MTGGame 继承和访问方法/属性并更新它们的能力,但是如果我使用super().__init__,那么在制作 MTGCards 时,我需要调用我的甲板作为 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属性/方法("能力列表"对象没有属性"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.

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

首先要注意的是: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属性,则卡牌不应具有此属性。继承的经验法则是"是"。由于卡"不是"玩家,它不应该继承自它或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 机制。祝你好运继续你的游戏!

最新更新