Skip to content

Commit c977bd1

Browse files
authored
Merge pull request github#13631 from github/ginsabch/DocumentExtendsFinal
document final extensions in the language reference
2 parents 634c838 + 621eca8 commit c977bd1

File tree

1 file changed

+72
-6
lines changed

1 file changed

+72
-6
lines changed

docs/codeql/ql-language-reference/types.rst

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,13 @@ the supertypes (that is, they are in the :ref:`class domain type <domain-types>`
112112
A class inherits all member predicates from its base types.
113113

114114
A class can extend multiple types. For more information, see ":ref:`multiple-inheritance`."
115+
A class can extend final types (or final aliases of types), see ":ref:`final-extensions`."
115116
Classes can also specialise other types without extending the class interface via `instanceof`,
116117
see ":ref:`instanceof-extensions`.".
117118

118119
To be valid, a class:
119120
- Must not extend itself.
120-
- Must not extend a :ref:`final` class.
121+
- Must not (transitively) extend a non-final type and a final alias of that same type.
121122
- Must not extend types that are incompatible. For more information, see ":ref:`type-compatibility`."
122123

123124
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:
134135
- Any number of :ref:`field <fields>` declarations.
135136

136137
When you define a class, that class also inherits all non-:ref:`private` member predicates and
137-
fields from its supertypes. You can :ref:`override <overriding-member-predicates>` those
138-
predicates and fields to give them a more specific definition.
138+
fields from its supertypes.
139+
140+
Depending on whether they are final, you can :ref:`override <overriding-member-predicates>` or
141+
:ref:`shadow <final-extensions>` those predicates and fields to give them a more specific definition.
139142

140143
.. _characteristic-predicates:
141144

@@ -242,6 +245,7 @@ A class :ref:`annotated <abstract>` with ``abstract``, known as an **abstract**
242245
the values in a larger type. However, an abstract class is defined as the union of its
243246
subclasses. In particular, for a value to be in an abstract class, it must satisfy the
244247
characteristic predicate of the class itself **and** the characteristic predicate of a subclass.
248+
Note that final extensions are not considered subclasses in this context.
245249

246250
An abstract class is useful if you want to group multiple existing classes together
247251
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.
281285
Overriding member predicates
282286
============================
283287

284-
If a class inherits a member predicate from a supertype, you can **override** the inherited
285-
definition. You do this by defining a member predicate with the same name and arity as the
286-
inherited predicate, and by adding the ``override`` :ref:`annotation <override>`.
288+
If a class inherits a member predicate from a non-final supertype, you can **override** the
289+
inherited definition. You do this by defining a member predicate with the same name and arity
290+
as the inherited predicate, and by adding the ``override`` :ref:`annotation <override>`.
287291
This is useful if you want to refine the predicate to give a more specific result for the
288292
values in the subclass.
289293

@@ -382,6 +386,68 @@ from ``OneTwoThree`` and ``int``.
382386
must :ref:`override <overriding-member-predicates>` those definitions to avoid ambiguity.
383387
:ref:`Super expressions <super>` are often useful in this situation.
384388

389+
.. _final-extensions:
390+
391+
Final extensions
392+
================
393+
394+
A class can extend final types or final aliases of types. In that case, it inherits final
395+
versions of all the member predicates and fields of those supertypes.
396+
Member predicates that are inherited through final extensions cannot be overridden,
397+
but they can be shadowed.
398+
399+
For example, extending the class from the :ref:`first example <defining-a-class>`:
400+
401+
.. code-block:: ql
402+
403+
final class FinalOneTwoThree = OneTwoThree;
404+
405+
class OneTwoFinalExtension extends FinalOneTwoThree {
406+
OneTwoFinalExtension() {
407+
this = 1 or this = 2
408+
}
409+
410+
string getAString() {
411+
result = "One or two: " + this.toString()
412+
}
413+
}
414+
415+
The member predicate ``getAString()`` shadows the original definition of ``getAString()``
416+
from ``OneTwoThree``.
417+
418+
Different to overriding (see ":ref:`overriding-member-predicates`"),
419+
final extensions leave the extended type unchanged:
420+
421+
.. code-block:: ql
422+
423+
from OneTwoTree o
424+
select o, o.getAString()
425+
426+
+---+-------------------------+
427+
| o | ``getAString()`` result |
428+
+===+=========================+
429+
| 1 | One, two or three: 1 |
430+
+---+-------------------------+
431+
| 2 | One, two or three: 2 |
432+
+---+-------------------------+
433+
| 3 | One, two or three: 3 |
434+
+---+-------------------------+
435+
436+
However, when calling ``getAString()`` on ``OneTwoFinalExtension``, the original definition is shadowed:
437+
438+
.. code-block:: ql
439+
440+
from OneTwoFinalExtension o
441+
select o, o.getAString()
442+
443+
+---+-------------------------+
444+
| o | ``getAString()`` result |
445+
+===+=========================+
446+
| 1 | One or two: 1 |
447+
+---+-------------------------+
448+
| 2 | One or two: 2 |
449+
+---+-------------------------+
450+
385451
.. _instanceof-extensions:
386452

387453
Non-extending subtypes

0 commit comments

Comments
 (0)