Это нормальное поведение для языка ОО? - PullRequest
1 голос
/ 10 февраля 2011

Я определил этот класс:

class RequiredFormSet(BaseFormSet):
    def __init__(self, *args, **kwargs):
        super(RequiredFormSet, self).__init__(*args, **kwargs)

И переопределил этот метод:

def total_form_count(self):
    return self._total_form_count

Так получилось, что super(...).__init__ использует total_form_count() где-то в этой функции.Она вызывает мою функцию, а не определенную в базовом классе.

Думаю, я подумала, потому что я позвонила super(), она использовала бы свои собственные вещи, но, очевидно, в Python это не так,Так ли это работает на других языках, таких как C #?Если я вызову базовый конструктор, он все равно будет вызывать все производные функции оттуда?

Ответы [ 7 ]

4 голосов
/ 10 февраля 2011

Да, это типичное поведение ООП (полиморфизм), когда методы подкласса вызываются динамической диспетчеризацией.Это одна из причин, почему C # требует, чтобы программист пометил переопределяемый метод как virtual.Я уверен, что вы знакомы с этим понятием в целом, и сюрприз в основном связан с тем фактом, что это происходит в конструкторе.

Как вы заметили, это может быть очень опасно в конструкторах, потому чтоКонструктор суперкласса может вызывать метод подкласса, который может полагаться на свойства, инициализированные в конструкторе подкласса.Эта проблема явно отмечена в Effective Java, и вы можете прочитать больше об этом здесь: Что не так с переопределенными вызовами методов в конструкторах?

3 голосов
/ 10 февраля 2011

Это нормальное поведение в python, C # имеет такое же поведение (для виртуальных функций), C ++ - нет (некоторые люди считают это недостатком дизайна C ++). В C ++ это имеет значение, если вы вызываете переопределенную виртуальную функцию из конструктора или из другой функции-члена. Причина этого заключается в том, что при запуске конструктора суперкласса V-таблица не является полной.

3 голосов
/ 10 февраля 2011

Вы слышали о полиморфизме? Если нет, вы понятия не имеете, что такое ООП, и вам следует поискать его.

self, используемый конструктором базового класса, является, конечно, экземпляром производного класса ( same self), поэтому, когда он вызывает self.m(), реализация m отправляется динамически. Некоторые ОО-языки требуют явной аннотации методов, которые отправляются динамически (ключевое слово virtual) - хотя (как указал @Doc Brown) это не работает в конструкторах, особенно в C ++, в то время как другие делают его по умолчанию. В любом случае, полиморфизм является неотъемлемой частью ООП, и хотя в некоторых языках возможно получить статическую диспетчеризацию, полиморфизм является опцией only во многих языках и обычно предпочтительным способом во всех других. Так что да, это нормальное поведение.

3 голосов
/ 10 февраля 2011

Это нормальное поведение. Обратите внимание на первый аргумент: self . Это ссылка на объект, к которому вызываются методы, поэтому даже при вызове метода суперкласса любые переопределенные методы , которые вызывают методы, будут методами подкласса.

Единственный способ заставить его использовать метод суперкласса - использовать несвязанную ссылку, т.е. SuperClass.overridenMethod(self, param1, param2) ...

1 голос
/ 10 февраля 2011

В C ++ вы можете выбирать между двумя вариантами поведения в зависимости от того, объявлено total_form_count или нет virtual. Но в Python все методы ведут себя как virtual: объект всегда будет использовать методы из фактического типа объекта.

0 голосов
/ 10 февраля 2011

Да, это поведение называется полиморфизм .Поиск методов в каждом языке ООП выполняется из класса экземпляра объекта, а не из класса, в котором находится код.

0 голосов
/ 10 февраля 2011

В C ++ конструктор является своего рода особым случаем, вызовы виртуальных методов приводят к вызову методов самого класса (а не того, который находится в конце виртуальной цепочки).

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