[Python-ideas] method decorators @final and @override in Python 2.4

Nick Coghlan ncoghlan at gmail.com
Sun Mar 29 01:40:38 CET 2009


Ben Finney wrote:
> Péter Szabó <ptspts at gmail.com> writes:
> 
>> If Python had method decorators @final (meaning: it is an error to
>> override this method in any subclass)
> 
> What use case is there for this? It would have to be quite strong to
> override the Python philosophy that “we're all consenting adults
> here”, and that the programmer of the subclass is the one who knows
> best whether a method needs overriding.

Agreed - the base class author has no right to tell subclass authors
that they *can't* do something. They can give hints that something
shouldn't be messed with by using a leading underscore and leaving it
undocumented (or advising against overriding it in the documentation).

That said, if a @suggest_final decorator was paired with an
@override_final decorator, I could actually see the point: one thing
that can happen with undocumented private methods and attributes in a
large class heirarchy is a subclass *accidentally* overriding them,
which can then lead to bugs which are tricky to track down (avoiding
such conflicts is actually one of the legitimate use cases for name
mangling). A suggest_final/override_final decorator pair would flag
accidental naming conflicts in complicated heirarchies at class
definition time, while still granting the subclass author the ability to
replace the nominally 'final' methods if they found it necessary.

>> and @override (meaning: it is an error not having this method in a
>> superclass)
> 
> I'm not sure I understand this one, but if I'm right this is supported
> now with:
> 
>     class FooABC(object):
>         def frobnicate(self):
>             raise NotImplementedError("Must be implemented in derived class")

Even better:

>>> import abc
>>> class FooABC(): # use metaclass keyword arg in Py3k
...   __metaclass__ = abc.ABCMeta
...   @abc.abstractmethod
...   def must_override():
...     raise NotImplemented
...

>>> x = FooABC()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class FooABC with abstract methods
must_override

>>> class Fail(FooABC): pass
...
>>> x = Fail()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Fail with abstract methods
must_override

>>> class Succeed(FooABC):
...   def must_override(self):
...     print "Overridden!"
...
>>> x = Succeed()
>>> x.must_override()
Overridden!

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------



More information about the Python-ideas mailing list