Если вы действительно хотите, чтобы ошибка возникала, если один из подклассов пытается вызвать абстрактный метод суперкласса, то да, вы должны вызвать его вручную. (а затем создайте экземпляр класса Exception для команды повышения raise NotImplementedError()
, даже если он работает с классом напрямую)
Однако существующее поведение действительно удобно: если ваш абстрактный метод содержит только pass
, тогда вы можете иметь любое количество подклассов, наследующих ваш базовый класс, и если хотя бы один из них реализует абстрактный метод, он будет работать. Даже если все они вызывают эквивалентный метод super () без проверки чего-либо еще.
Если в сложной иерархии будет вызвана ошибка - NotImplementedError
или любая другая, использующая миксины, и например, вам нужно проверять каждый раз при вызове super
, возникла ли ошибка, просто чтобы ее пропустить. Для записи возможно проверить, попадет ли super()
в класс, где метод является абстрактным с условным условием, таким образом:
if not getattr(super().foo, "__isabstractmethod__", False):
super().foo(...)
Так как вы хотите, если вы достигнете основы иерархии для метод состоит в том, чтобы ничего не делать, это очень просто, если просто ничего не происходит!
Я имею в виду, проверьте это:
class A(abc.ABC):
@abstractmethod
def validate(self, **kwargs):
pass
class B(A):
def validate(self, *, first_arg_for_B, second_arg_for_B=None, **kwargs):
super().validate(**kwargs)
# perform validation:
...
class C(A)
def validate(self, *, first_arg_for_C **kwargs):
super().validate(**kwargs)
# perform validation:
...
class Final(B, C):
...
Ни B.validate
, ни C.validate
не нужно беспокоиться о любой другой класс в иерархии, просто делай свое дело и передавай дальше. Если A.validate вызовет повышение, оба метода должны будут выполнить super().validate(...)
внутри оператора try: ...;except ...:pass
или внутри странного if
блока, чтобы получить ... ничего.
обновление - я только что нашел это примечание в официальной документации:
Примечание В отличие от Java абстрактных методов, эти абстрактные методы могут иметь реализацию. Эта реализация может быть вызвана через механизм super () из класса, который ее переопределяет. Это может быть полезно в качестве конечной точки для супер-вызова в платформе, которая использует кооперативное множественное наследование. https://docs.python.org/3/library/abc.html#abc .abstractmethod
Я даже верну вам личный вопрос, если вы можете ответить в комментариях: я понимаю, что он гораздо менее актуален в Java, где один не может иметь множественное наследование, поэтому даже в большой иерархии первый подкласс для реализации абстрактного метода обычно хорошо известен. Но в противном случае в проекте Java можно было бы выбрать один из различных базовых классов бетона и продолжить работу с другими в произвольном порядке, поскольку метод абстрактности повышается, как это разрешается?