Many popular programming languages support override checks. For example:
-`C++ has <https://en.cppreference.com/w/cpp/language/override/>`_``override``.
-`C# has <https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/override/>`_``override``.
-`Hack has <https://docs.hhvm.com/hack/attributes/predefined-attributes#__override/>`_``<<__Override>>``.
-`Java has <https://docs.oracle.com/javase/tutorial/java/IandI/override.html/>`_``@Override``.
-`Kotlin has <https://kotlinlang.org/docs/inheritance.html#overriding-methods/>`_``override``.
-`Scala has <https://www.javatpoint.com/scala-method-overriding/>`_``override``.
-`Swift has <https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html#ID198/>`_``override``.
-`Typescript has <https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html#override-and-the---noimplicitoverride-flag/>`_``override``.
Runtime Override Checks in Python
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Today, there is an `Overrides library <https://pypi.org/project/overrides/>`_
that provides decorators ``@overrides`` (sic) and ``@final`` and will enforce
them at runtime.
:pep:`591` added a ``@final`` decorator with the same semantics as those in the
Overrides library. But the override component of the runtime library is not
supported statically at all, which has added some confusion around the
mix/matched support.
Providing support for ``@override`` in static checks would add value because
- Bugs can be caught earlier, often in-editor.
- Static checks come with no performance overhead, unlike runtime checks.
- Bugs will be caught quickly even in rarely-used modules, whereas with runtime
checks these might go undetected for a time without automated tests of all
imports.
Disadvantages
-------------
The two disadvantages we are aware of to using ``@override`` are that
- The code becomes more verbose - overriding methods require one additional
line.
- Adding or removing base class methods that impact overrides will require
updating subclass code.
Specification
=============
When type checkers encounter a method decorated with ``@typing.override`` they
should treat it as a type error unless that method is overriding a compatible
method or attribute in some ancestor class.
..code-block:: python
from typing import override
class Parent:
def foo(self) -> int:
return 1
def bar(self, x: str) -> str:
return x
class Child(Parent):
@override
def foo(self) -> int:
return 2
@override
def baz() -> int: # Type check error: no matching signature in ancestor
return 1
The ``@override`` decorator should be permitted anywhere a type checker
considers a method to be a valid override, which typically includes not only
normal methods but also ``@property``, ``@staticmethod``, and ``@classmethod``.
Override Compatibility Rules are Unchanged
------------------------------------------
Type checkers already enforce compatibility rules for overrides; for example, a
subclass method’s type signature should be compatible with that of the
superclass method. These compatibility rules do not change due to the presence
or absence of ``@override``.
Note that when a ``@property`` overrides a regular attribute of the base class,
this should not be considered an error due to the use of ``@override``, but the
type checker may still consider the override to be incompatible. For example a
type checker may consider it illegal to override a non-final attribute with a
getter property and no setter, as this does not respect the substitution
principle.
Strict Enforcement Per-Project
==============================
We plan to make the use of ``@override`` required in Pyre’s strict mode. This
is a feature we believe most type checkers would benefit from.
Motivation
----------
The primary reason for a strict mode that requires ``@override`` is that developers
can only trust that refactors are override-safe if they know that the ``@override``
decorator is used throughout the project.
There is another class of bug related to overrides that we can only catch using a strict mode.
- Pyre can `type-check this decorator <https://github.com/facebook/pyre-check/blob/ae68c44f4e5b263ce0e175f0798272d9318589af/source/analysis/test/integration/methodTest.ml#L2515-L2638/>`_
as specified in this PEP
Copyright
=========
This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.