Вызов переопределенного метода, суперкласс вызов переопределенного метода - PullRequest
15 голосов
/ 22 октября 2011

Этот код генерирует исключение, 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()

Ответы [ 4 ]

8 голосов
/ 22 октября 2011

В классе A вместо вызова self методов вам нужно вызвать A методы и передать 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()
6 голосов
/ 22 октября 2011

Работает так, как задумано, так как работают 100% мировых языков программирования. Подкласс переопределяет ВСЕ методы родительского класса.

Однако, если вы действительно хотите вызвать A.foo1 (), вы можете сделать это следующим образом (я не могу гарантировать). И в любом случае вы не должны этого делать, поскольку это противоречит всем принципам хорошего программирования.

 class A(object):

    def foo(self):
        A.foo1(self)
4 голосов
/ 22 октября 2011

В коде:

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

self является экземпляром B.

Когда метод, производный от A, вызывается экземпляром B, он начинает искать в пространстве имен изB, и только если метод не найден (например, не переопределен B), используется реализация из A, но всегда с self, ссылающимся на B. Ни в коем случае self не является экземпляром A.

0 голосов
/ 12 апреля 2013

Здесь видно, что делает Python, но способ переопределения немного экстремален.Возьмите случай, когда класс A определяет 100 атрибутов, а класс B наследует их, и добавьте еще 1 атрибут.Мы хотим, чтобы __init __ () для B вызывал __init __ () для A, и чтобы код B определял только его единственный атрибут.Точно так же, если мы определим метод reset () в A, чтобы установить все атрибуты на ноль, то соответствующий метод reset () для B должен иметь возможность просто вызвать метод reset () для A, а затем обнулять единственный атрибут B вместонеобходимости дублировать весь код А.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()

(Чтобы это работало правильно, удалите вызов self.reset () в __init __ () для класса Y.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...