【问题标题】:Alternative for inheritance in pythonpython中继承的替代方案
【发布时间】:2013-07-16 03:06:05
【问题描述】:

以下场景如何保存代码重复?

AB是两个具有共同功能的类(比如)name

class A(object):
    name = 'foo'

    @property
    def name(self):  # the common function
        return self.name

类似地

class B(object):
    name = 'bar'

    @property
    def name(self):
        return self.name

一种方法是创建一个它们都继承自的类,并在那里定义name

有什么好的选择吗?

【问题讨论】:

标签: python


【解决方案1】:

如果你真的决定避免继承,只需在任一类之外定义一个函数:

def get_name(object):
    return object.name

【讨论】:

    【解决方案2】:
    class A(object):
        name = 'foo'
    
        def get_name(self):  # the common function
            return self.name
    
    class B(A):
        pass
    

    在这种情况下,B 将继承自 A

    【讨论】:

      【解决方案3】:

      你有什么理由不能让 B 从 A 继承?

      class B(A):
          name = 'bar'
      

      【讨论】:

      • 嗯,A 不是从 B 继承的。只是 A 的 B,常规继承的问题在哪里?
      【解决方案4】:

      由于您使用@property 装饰name,我假设您希望这是一个实例变量。如果你想让它返回一个更私有的变量,我们称之为_name,你必须这样做:

      class A(object):
          def __init__(self):
              self._name = 'foo'
      
          @property
          def name(self):
              return self._name
      

      变量和函数不能同名,因为后者会简单地覆盖前者。如果你想要一个处理这个问题的基类,它看起来像这样:

      class HasName(object):
          def __init__(self, name):
              self._name = name
      
          @property
          def name(self):
              return self._name
      
      class A(HasName):
           def __init__(self):
               self._name = 'foo'
      
      class B(HasName):
           def __init__(self):
               self._name = 'bar'
      

      也可以调用HasName中的构造函数。

      【讨论】:

        【解决方案5】:

        假设self.name 代表一个更复杂的方法,减少重复代码的最简单方法是将函数移到模块中,并将任意对象作为参数。然后,如果您仍想将该方法直接绑定到该类,您可以添加一个短方法来调度到模块函数。

        def _name(obj):
            return obj.name
        
        class A(object):
             # ...
        
             @property
             def name(self):
                 return _name(self)
        
        class B(object):
             # ...
        
             @property
             def name(self):
                 return _name(self)
        

        请注意,如果A.nameB.name 具有完全不同的行为,这将不会正常工作。如果_name 函数开始检查给定对象的类型,请重新考虑您是否真的要首先抽象该功能。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-12-14
          • 1970-01-01
          • 2013-06-18
          • 1970-01-01
          • 2014-10-22
          • 2015-05-30
          • 1970-01-01
          相关资源
          最近更新 更多