【问题标题】:Calling an overridden method, superclass an calls overridden method调用被覆盖的方法,超类调用被覆盖的方法
【发布时间】:2011-12-13 03:53:34
【问题描述】:

这段代码抛出了一个异常,AttributeError, "wtf!",因为A.foo()正在调用B.foo1(),它不应该调用A.foo1()吗?如何强制它调用A.foo1()A.foo() 中的任何方法调用都应该调用A.*

class A(object):
    def foo(self):
        print self.foo1()

    def foo1(self):
        return "foo"

class B(A):
    def foo1(self):
        raise AttributeError, "wtf!"

    def foo(self):
        raise AttributeError, "wtf!"

    def foo2(self):
        super(B, self).foo()

myB = B()
myB.foo2()

【问题讨论】:

  • 您基本上是在要求 Python 抛弃动态性和虚拟方法,并且 不知何故 根据函数的词法定义位置找出跳过属性查找链的部分内容。不会发生。
  • 我认为这是糟糕设计的标志。如果你在你的子类中重写了一个方法,但你不希望它被调用,这难道不是你做错了什么的迹象吗?我认为你应该重新考虑你的类层次结构——也许B 不应该是A 的子类。
  • 我还是有同样的问题。 B.foo2 可以是对A.foo 实现的增强(例如,在B.foo2 中的super 行之后再添加一行)。在这种情况下,您希望A.foo 调用A.foo1,即按原意调用父实现,然后才对其进行增强。下面的答案围绕在B.foo2 中显式使用A.foo(self) 或更糟糕的是在A.foo 中显式使用A.foo1(self)。但是答案可能会更改Asuper 是为了解决这个问题,对吧?

标签: python inheritance superclass


【解决方案1】:

它按预期工作,因为世界上 100% 的编程语言都在工作。子类覆盖父类的所有方法。

但是,如果您真的想调用 A.foo1(),您可以这样做(我不能保证)。在任何情况下,您都不能这样做,因为这违反了良好编程的所有原则。

 class A(object):

    def foo(self):
        A.foo1(self)

【讨论】:

    【解决方案2】:

    在代码中:

    def foo2(self):
        super(B, self).foo()
    

    self 是 B 的一个实例。

    当从 A 派生的方法被 B 的实例调用时,它将开始在 B 的命名空间中查找,并且只有在未找到该方法(例如未被 B 覆盖)时才使用来自 A 的实现,但是总是 self 指代 B。在任何时候 self 都不是 A 的实例。

    【讨论】:

      【解决方案3】:

      在 A 类中,您需要调用 A 方法并手动传入 self,而不是调用 self 方法。

      这不是正常的做事方式——你应该有一个真的很好的理由这样做。

      class A(object):
          def foo(self):
              print A.foo1(self)
      
          def foo1(self):
              return "foo"
      
      class B(A):
          def foo1(self):
              raise AttributeError, "wtf!"
      
          def foo(self):
              raise AttributeError, "wtf!"
      
          def foo2(self):
              super(B, self).foo()
      
      myB = B()
      myB.foo2()
      

      【讨论】:

        【解决方案4】:

        这里可以看到Python在做什么,但是覆盖的方式有点极端。以 A 类定义 100 个属性而 B 类继承这些属性并添加 1 个属性为例。我们希望能够让 B 的 __init__() 调用 A 的 __init__() 并让 B 的代码只定义它的单个属性。类似地,如果我们在 A 中定义一个 reset() 方法将所有属性设置为零,那么 B 的相应 reset() 方法应该能够只调用 A 的 reset() 方法,然后将单个 B 属性清零不必复制所有 A 的代码。 Python 使本应是面向对象编程的主要优势变得困难。也就是代码的重用。这里最好的选择是避免覆盖我们真正想要重用的方法。如果您想在这里了解 Python 的复杂性,请尝试以下代码:

        class X(object):
            def __init__ ( self ):
                print "X"
                self.x = 'x'
                self.reset()
                print "back to X"
            def reset ( self ):
                print "reset X"
                self.xx = 'xx'
        
        class Y(X):
            def __init__ ( self ):
                print "Y"
                super(Y,self).__init__()
                self.y = 'y'
                self.reset()
                print "back to Y"
            def reset ( self ):
                print "reset Y"
                super(Y,self).reset()
                print "back to reset Y"
                self.yy = 'yy'
        
        aY = Y()
        

        (为了使这项工作正常进行,请删除类 Y 的 __init__() 中的 self.reset() 调用。)

        【讨论】:

        • 这并没有回答问题,只是提供了 Python 中的问题示例。
        猜你喜欢
        • 2010-10-18
        • 1970-01-01
        • 2014-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-27
        • 1970-01-01
        • 2010-11-29
        相关资源
        最近更新 更多