mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge pull request #13631 from github/ginsabch/DocumentExtendsFinal
document final extensions in the language reference
This commit is contained in:
@@ -112,12 +112,13 @@ the supertypes (that is, they are in the :ref:`class domain type <domain-types>`
|
||||
A class inherits all member predicates from its base types.
|
||||
|
||||
A class can extend multiple types. For more information, see ":ref:`multiple-inheritance`."
|
||||
A class can extend final types (or final aliases of types), see ":ref:`final-extensions`."
|
||||
Classes can also specialise other types without extending the class interface via `instanceof`,
|
||||
see ":ref:`instanceof-extensions`.".
|
||||
|
||||
To be valid, a class:
|
||||
- Must not extend itself.
|
||||
- Must not extend a :ref:`final` class.
|
||||
- Must not (transitively) extend a non-final type and a final alias of that same type.
|
||||
- Must not extend types that are incompatible. For more information, see ":ref:`type-compatibility`."
|
||||
|
||||
You can also annotate a class. See the list of :ref:`annotations <annotations-overview>`
|
||||
@@ -134,8 +135,10 @@ The body of a class can contain:
|
||||
- Any number of :ref:`field <fields>` declarations.
|
||||
|
||||
When you define a class, that class also inherits all non-:ref:`private` member predicates and
|
||||
fields from its supertypes. You can :ref:`override <overriding-member-predicates>` those
|
||||
predicates and fields to give them a more specific definition.
|
||||
fields from its supertypes.
|
||||
|
||||
Depending on whether they are final, you can :ref:`override <overriding-member-predicates>` or
|
||||
:ref:`shadow <final-extensions>` those predicates and fields to give them a more specific definition.
|
||||
|
||||
.. _characteristic-predicates:
|
||||
|
||||
@@ -242,6 +245,7 @@ A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract**
|
||||
the values in a larger type. However, an abstract class is defined as the union of its
|
||||
subclasses. In particular, for a value to be in an abstract class, it must satisfy the
|
||||
characteristic predicate of the class itself **and** the characteristic predicate of a subclass.
|
||||
Note that final extensions are not considered subclasses in this context.
|
||||
|
||||
An abstract class is useful if you want to group multiple existing classes together
|
||||
under a common name. You can then define member predicates on all those classes. You can also
|
||||
@@ -281,9 +285,9 @@ there is no need to update the queries that rely on it.
|
||||
Overriding member predicates
|
||||
============================
|
||||
|
||||
If a class inherits a member predicate from a supertype, you can **override** the inherited
|
||||
definition. You do this by defining a member predicate with the same name and arity as the
|
||||
inherited predicate, and by adding the ``override`` :ref:`annotation <override>`.
|
||||
If a class inherits a member predicate from a non-final supertype, you can **override** the
|
||||
inherited definition. You do this by defining a member predicate with the same name and arity
|
||||
as the inherited predicate, and by adding the ``override`` :ref:`annotation <override>`.
|
||||
This is useful if you want to refine the predicate to give a more specific result for the
|
||||
values in the subclass.
|
||||
|
||||
@@ -382,6 +386,68 @@ from ``OneTwoThree`` and ``int``.
|
||||
must :ref:`override <overriding-member-predicates>` those definitions to avoid ambiguity.
|
||||
:ref:`Super expressions <super>` are often useful in this situation.
|
||||
|
||||
.. _final-extensions:
|
||||
|
||||
Final extensions
|
||||
================
|
||||
|
||||
A class can extend final types or final aliases of types. In that case, it inherits final
|
||||
versions of all the member predicates and fields of those supertypes.
|
||||
Member predicates that are inherited through final extensions cannot be overridden,
|
||||
but they can be shadowed.
|
||||
|
||||
For example, extending the class from the :ref:`first example <defining-a-class>`:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
final class FinalOneTwoThree = OneTwoThree;
|
||||
|
||||
class OneTwoFinalExtension extends FinalOneTwoThree {
|
||||
OneTwoFinalExtension() {
|
||||
this = 1 or this = 2
|
||||
}
|
||||
|
||||
string getAString() {
|
||||
result = "One or two: " + this.toString()
|
||||
}
|
||||
}
|
||||
|
||||
The member predicate ``getAString()`` shadows the original definition of ``getAString()``
|
||||
from ``OneTwoThree``.
|
||||
|
||||
Different to overriding (see ":ref:`overriding-member-predicates`"),
|
||||
final extensions leave the extended type unchanged:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
from OneTwoTree o
|
||||
select o, o.getAString()
|
||||
|
||||
+---+-------------------------+
|
||||
| o | ``getAString()`` result |
|
||||
+===+=========================+
|
||||
| 1 | One, two or three: 1 |
|
||||
+---+-------------------------+
|
||||
| 2 | One, two or three: 2 |
|
||||
+---+-------------------------+
|
||||
| 3 | One, two or three: 3 |
|
||||
+---+-------------------------+
|
||||
|
||||
However, when calling ``getAString()`` on ``OneTwoFinalExtension``, the original definition is shadowed:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
from OneTwoFinalExtension o
|
||||
select o, o.getAString()
|
||||
|
||||
+---+-------------------------+
|
||||
| o | ``getAString()`` result |
|
||||
+===+=========================+
|
||||
| 1 | One or two: 1 |
|
||||
+---+-------------------------+
|
||||
| 2 | One or two: 2 |
|
||||
+---+-------------------------+
|
||||
|
||||
.. _instanceof-extensions:
|
||||
|
||||
Non-extending subtypes
|
||||
|
||||
Reference in New Issue
Block a user