《Python面向对象编程指南》——1.6 在每个子类中实现

    xiaoxiao2024-04-08  113

    本节书摘来自异步社区《Python面向对象编程指南》一书中的第1章,第1.6节,作者[美]Steven F. Lott, 张心韬 兰亮 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

    1.6 在每个子类中实现__init()__方法

    正如介绍工厂函数那样,这里我们也先看一些Card类的设计实例。我们可以考虑重构rank数值转换的代码,并把这个功能加在Card类上。这样就可以把初始化的工作分发到每个子类来完成。

    这通常需要在基类中完成一些公共的初始化逻辑,子类中完成各自特殊的初始化逻辑。我们需要遵守不要重复自己(Don't Repeat Yourself,DRY)的原则来防止子类中的代码重复。

    以下代码演示了如何把初始化职责分发到各自的子类中。

    class Card:   pass class NumberCard( Card ):   def __init__( self, rank, suit ):     self.suit= suit     self.rank= str(rank)     self.hard = self.soft = rank class AceCard( Card ):   def __init__( self, rank, suit ):     self.suit= suit     self.rank= "A"     self.hard, self.soft = 1, 11 class FaceCard( Card ):   def __init__( self, rank, suit ):     self.suit= suit     self.rank= {11: 'J', 12: 'Q', 13: 'K' }[rank]     self.hard = self.soft = 1

    上例代码是多态的实现,由于缺乏公共初始化函数,导致了一些不受欢迎的重复代码。以上代码的主要重复部分是对suit的赋值。这部分代码放在基类中显然比较合适。我们可以在子类中显式调用基类的__init()__方法。

    以下代码演示了如何把__init()__方法提到基类Card中实现的过程,然后在子类中可以重用基类的实现。

    class Card:   def __init__( self, rank, suit, hard, soft ):     self.rank= rank     self.suit= suit     self.hard= hard     self.soft= soft class NumberCard( Card ):   def __init__( self, rank, suit ):     super().__init__( str(rank), suit, rank, rank ) class AceCard( Card ):   def __init__( self, rank, suit ):     super().__init__( "A", suit, 1, 11 ) class FaceCard( Card ):   def __init__( self, rank, suit ):     super().__init__( {11: 'J', 12: 'Q', 13: 'K' }[rank], suit, 10, 10 )

    我们在子类和基类中都提供了__init()__方法的实现,这样会在一定程度上简化工厂函数的逻辑,如下面代码段所示。

    def card10( rank, suit ):   if rank == 1: return AceCard( rank, suit )   elif 2 <= rank < 11: return NumberCard( rank, suit )   elif 11 <= rank < 14: return FaceCard( rank, suit )   else:     raise Exception( "Rank out of range" )

    仅仅是简化工厂函数不应该是我们重构焦点的全部。我们还应该看到这次的重构导致__init()__方法变得复杂了,做这样的权衡是正常的。

    相关资源:敏捷开发V1.0.pptx
    最新回复(0)